das*_*uki 2 python conditional data-structures
我想知道是否有任何方法可以简化以下的代码.正如您所看到的,使用了许多dicts以及条件语句来清除错误的输入数据.请注意,行程速率值尚未全部输入,现在只复制和粘贴dicts
编辑
在任何一个比率中,(x,y):z.x和y是正确的,z值不是因为它们只是复制/粘贴
此代码适用于您要复制,粘贴和测试它的情况
import math
# step 1.4 return trip rates
def trip_rates( population_stratification, analysis_type, low_income, medium_income, high_income ):
''' this function returns the proper trip rate tuple to be used based on input
data
ADPT = Average Daily Person Trips per Household
pph = person per household
veh_hh = vehicles per household
(param_1, param_2): ADPT
'''
li = low_income
mi = medium_income
hi = high_income
# table 5 -
if analysis_type == 1:
if population_stratification == 1:
rates = {( li, 1 ):3.6, ( li, 2 ):6.5, ( li, 3 ):9.1, ( li, 4 ):11.5, ( li, 5 ): 13.8,
( mi, 1 ):3.9, ( mi, 2 ):7.3, ( mi, 3 ):10.0, ( mi, 4 ):13.1, ( mi, 5 ): 15.9,
( hi, 1 ):4.5, ( mi, 2 ):9.2, ( mi, 3 ):12.2, ( mi, 4 ):14.8, ( mi, 5 ): 18.2}
return rates
if population_stratification == 2:
rates = {
( li, 1 ):3.1, ( li, 2 ):6.3, ( li, 3 ):9.4, ( li, 4 ):12.5, ( li, 5 ): 14.7,
( mi, 1 ):4.8, ( mi, 2 ):7.2, ( mi, 3 ):10.1, ( mi, 4 ):13.3, ( mi, 5 ): 15.5,
( hi, 1 ):4.9, ( mi, 2 ):7.7, ( mi, 3 ):12.5, ( mi, 4 ):13.8, ( mi, 5 ): 16.7
}
return rates
if population_stratification == 3: #TODO: input actual rate
rates = {
( li, 1 ):3.6, ( li, 2 ):6.5, ( li, 3 ):9.1, ( li, 4 ):11.5, ( li, 5 ): 13.8,
( mi, 1 ):3.9, ( mi, 2 ):7.3, ( mi, 3 ):10.0, ( mi, 4 ):13.1, ( mi, 5 ): 15.9,
( hi, 1 ):4.5, ( mi, 2 ):9.2, ( mi, 3 ):12.2, ( mi, 4 ):14.8, ( mi, 5 ): 18.2
}
return rates
if population_stratification == 4: #TODO: input actual rate
rates = {
( li, 1 ):3.1, ( li, 2 ):6.3, ( li, 3 ):9.4, ( li, 4 ):12.5, ( li, 5 ): 14.7,
( mi, 1 ):4.8, ( mi, 2 ):7.2, ( mi, 3 ):10.1, ( mi, 4 ):13.3, ( mi, 5 ): 15.5,
( hi, 1 ):4.9, ( mi, 2 ):7.7, ( mi, 3 ):12.5, ( mi, 4 ):13.8, ( mi, 5 ): 16.7
}
return rates
#table 6
elif analysis_type == 2:
if population_stratification == 1: #TODO: Change rates
rates = {
( 0, 1 ):3.6, ( 0, 2 ):6.5, ( 0, 3 ):9.1, ( 0, 4 ):11.5, ( 0, 5 ): 13.8,
( 1, 1 ):3.9, ( 1, 2 ):7.3, ( 1, 3 ):10.0, ( 1, 4 ):13.1, ( 1, 5 ): 15.9,
( 2, 1 ):4.5, ( 2, 2 ):9.2, ( 2, 3 ):12.2, ( 2, 4 ):14.8, ( 2, 5 ): 18.2,
( 3, 1 ):4.5, ( 3, 2 ):9.2, ( 3, 3 ):12.2, ( 3, 4 ):14.8, ( 3, 5 ): 18.2
}
return rates
if population_stratification == 2: #TODO: Change rates
rates = {
( 0, 1 ):3.6, ( 0, 2 ):6.5, ( 0, 3 ):9.1, ( 0, 4 ):11.5, ( 0, 5 ): 13.8,
( 1, 1 ):3.9, ( 1, 2 ):7.3, ( 1, 3 ):10.0, ( 1, 4 ):13.1, ( 1, 5 ): 15.9,
( 2, 1 ):4.5, ( 2, 2 ):9.2, ( 2, 3 ):12.2, ( 2, 4 ):14.8, ( 2, 5 ): 18.2,
( 3, 1 ):4.5, ( 3, 2 ):9.2, ( 3, 3 ):12.2, ( 3, 4 ):14.8, ( 3, 5 ): 18.2
}
return rates
if population_stratification == 3: #TODO: Change rates
rates = {
( 0, 1 ):3.6, ( 0, 2 ):6.5, ( 0, 3 ):9.1, ( 0, 4 ):11.5, ( 0, 5 ): 13.8,
( 1, 1 ):3.9, ( 1, 2 ):7.3, ( 1, 3 ):10.0, ( 1, 4 ):13.1, ( 1, 5 ): 15.9,
( 2, 1 ):4.5, ( 2, 2 ):9.2, ( 2, 3 ):12.2, ( 2, 4 ):14.8, ( 2, 5 ): 18.2,
( 3, 1 ):4.5, ( 3, 2 ):9.2, ( 3, 3 ):12.2, ( 3, 4 ):14.8, ( 3, 5 ): 18.2
}
return rates
if population_stratification == 4: #TODO: Change rates
rates = {
( 0, 1 ):3.6, ( 0, 2 ):6.5, ( 0, 3 ):9.1, ( 0, 4 ):11.5, ( 0, 5 ): 13.8,
( 1, 1 ):3.9, ( 1, 2 ):7.3, ( 1, 3 ):10.0, ( 1, 4 ):13.1, ( 1, 5 ): 15.9,
( 2, 1 ):4.5, ( 2, 2 ):9.2, ( 2, 3 ):12.2, ( 2, 4 ):14.8, ( 2, 5 ): 18.2,
( 3, 1 ):4.5, ( 3, 2 ):9.2, ( 3, 3 ):12.2, ( 3, 4 ):14.8, ( 3, 5 ): 18.2
}
return rates
# table 7
elif analysis_type == 3:
if population_stratification == 1: #TODO: input actual rate
rates = {
( li, 0 ):3.6, ( li, 1 ):6.5, ( li, 2 ):9.1, ( li, 3 ):11.5,
( mi, 0 ):3.9, ( mi, 1 ):7.3, ( mi, 2 ):10.0, ( mi, 3 ):13.1,
( hi, 0 ):4.5, ( mi, 1 ):9.2, ( mi, 2 ):12.2, ( mi, 3 ):14.8
}
return rates
if population_stratification == 2: #TODO: input actual rate
rates = {
( li, 0 ):3.6, ( li, 1 ):6.5, ( li, 2 ):9.1, ( li, 3 ):11.5,
( mi, 0 ):3.9, ( mi, 1 ):7.3, ( mi, 2 ):10.0, ( mi, 3 ):13.1,
( hi, 0 ):4.5, ( mi, 1 ):9.2, ( mi, 2 ):12.2, ( mi, 3 ):14.8
}
return rates
if population_stratification == 3: #TODO: input actual rate
rates = {
( li, 0 ):3.6, ( li, 1 ):6.5, ( li, 2 ):9.1, ( li, 3 ):11.5,
( mi, 0 ):3.9, ( mi, 1 ):7.3, ( mi, 2 ):10.0, ( mi, 3 ):13.1,
( hi, 0 ):4.5, ( mi, 1 ):9.2, ( mi, 2 ):12.2, ( mi, 3 ):14.8
}
return rates
if population_stratification == 4: #TODO: input actual rate
rates = {
( li, 0 ):3.6, ( li, 1 ):6.5, ( li, 2 ):9.1, ( li, 3 ):11.5,
( mi, 0 ):3.9, ( mi, 1 ):7.3, ( mi, 2 ):10.0, ( mi, 3 ):13.1,
( hi, 0 ):4.5, ( mi, 1 ):9.2, ( mi, 2 ):12.2, ( mi, 3 ):14.8
}
return rates
def interpolate( population_stratification, analysis_type, low_income, medium_income, high_income, x, y ):
#get rates dict
rates = trip_rates( population_stratification, analysis_type, low_income, medium_income, high_income )
# dealing with x parameters
#when using income levels, x_1 and x_2 are li, mi, or hi
if analysis_type == 1 or analysis_type == 2 or analsis_type == 4:
if x < high_income and x >= medium_income:
x_1 = medium_income
x_2 = high_income
elif x < medium_income:
x_1 = low_income
x_2 = medium_income
else:
x_1 = high_income
x_2 = high_income
if analysis_type == 3:
if x >= 3:
x_1 = 3
x_2 = 3
else:
x_1 = int( math.floor( x ) )
x_2 = int( math.ceil( x ) )
# dealing with y parametrs
#when using persons per household, max number y = 5
if analysis_type == 1 or analysis_type == 4:
if y >= 5:
y_1 = 5
y_2 = 5
else:
y_1 = int( math.floor( y ) )
y_2 = int( math.ceil( y ) )
elif analysis_type == 2 or analysis_type == 3:
if y >= 5:
y_1 = 5
y_2 = 5
else:
y_1 = int( math.floor( y ) )
y_2 = int( math.ceil( y ) )
# denominator
z = ( ( x_2 - x_1 ) * ( y_2 - y_1 ) )
result = ( ( ( rates[( x_1, y_1 )] ) * ( ( x_2 - x ) * ( y_2 - y ) ) / ( z ) ) +
( ( rates[( x_2, y_1 )] ) * ( ( x - x_1 ) * ( y_2 - y ) ) / ( z ) ) +
( ( rates[( x_1, y_2 )] ) * ( ( x_2 - x ) * ( y - y_1 ) ) / ( z ) ) +
( ( rates[( x_2, y_2 )] ) * ( ( x - x_1 ) * ( y - y_1 ) ) / ( z ) ) )
return result
#test
low_income = 20000 #this is calculated using exchange rates
medium_income = 40000 # this is calculated using exchange rates
high_income = 60000 # this is calculated using exchange rates
population_stratification = 1 #inputed by user
analysis_type = 1 #inputed by user
x = 35234.34 #test income
y = 3.5 # test pph
print interpolate( population_stratification, analysis_type, low_income, medium_income, high_income, x, y )
Run Code Online (Sandbox Code Playgroud)
那么,从哪里开始?这是第一个观察:
那里有很多数据,似乎代码和数据相互混合.
数据和代码应该是分开的.数据是外部源,您可以修改或读入.您可以调整代码以快速将数据从良好的可编辑表示解析为对算法有用的表示.我怀疑你的代码会更短,更清晰,更不容易出错(你是否注意到所有'rate'词典都有多个键,你错过了很多'hi'键?).
如果您需要更好的抽象,如矩阵和数据数组,请查看 numpy
编辑1
你算了几个尺寸吗?这里有一个带有X维度的多维矩阵:analysis_type,population_stratification,income_level,index
如果我看到这是一个3x4x3x3(= 108个条目)"矩阵"或"查找表".如果这是您的模型构建的数据,那很好.但是你不能把这些数字放在你读过的文件或表格中吗?你的代码将是微不足道的.
编辑2
好吧,我会咬一些小的python风格:测试Set或Range中的值.
代替:
if analysis_type == 1 or analysis_type == 2 or analsis_type == 4:
Run Code Online (Sandbox Code Playgroud)
您可以使用
if analysis_type in (1, 2, 4):
Run Code Online (Sandbox Code Playgroud)
甚至根据建议使用可读名称(CUBIC,..).
代替:
if x < high_income and x >= medium_income:
Run Code Online (Sandbox Code Playgroud)
你可以使用链式条件; Python是少数编程语言之一,其中条件链为if中性if语句:
if medium_income <= x < high_income:
Run Code Online (Sandbox Code Playgroud)
编辑3
比小代码数字更重要的当然是代码设计和重构.编辑2只能给你一些润色.
你应该学会厌恶重复的代码.
此外,在一个函数中有很多分支.这是一个好的迹象,你应该把它分解成多个功能.它还可以减少重复.例如,当一个变量像analysis_type可以完全改变函数所做的那样时,为什么在一个函数中有两个不同的行为?你不应该把整个程序放在一个函数中.也许analysis_type == 3在其自身的功能中更好地表达(作为例子)?
你明白你的函数trip_rates基本上是一个数组查找,其中数组查找是硬编码的,好像..:return .. if:return ..,并且数组在函数中完全写出来?如果trip_rates可以这样实现怎么办?可能吗?
data_model = compute_table(low_income, ...)
return data_model[analysis_type][population_stratification]
Run Code Online (Sandbox Code Playgroud)