我有以下词典:
input_processed = {'units' : {'g' : 'g',
'dx' : 'cm',
'po' : 'bar',
'muo' : 'mPas'},
'g' : 1.0,
'dx' : [10.0, 20.0, 10.0],
'muo' : {'po' : [0.0, 1.0],
'muo' : [32.7, 32.7]},
'phi' : 0.05}
commands_variables = {'units' : [],
'g' : ['g'],
'dx' : ['dx'],
'muo' : ['po', 'muo'],
'phi' : ['phi']}
conversion_factors = {'g' : 9.81,
'cm' : 0.01,
'bar' : 10**5,
'mPas' : 10**-3}
我的目标是将input_processed
中的每个浮点数乘以conversion_factors
中为某些变量定义的因子。由于命令(input_processed
中的最高级别键可以定义多个变量,因此这些变量将映射到commands_variables
。
首先,我需要检查input_processed['units']
中是否包含变量,因为phi
没有单位。然后对于每个命令中的每个变量,我需要获得该单元。在下一步中,我将根据conversion_factors
中的单位获得转换因子。由于input_processed
中最高级别键的值可以是float,list或dict类型,因此我为每种情况编写了不同的方法。这被放入一个函数中,并在input_processed
的循环中调用。
def convert_unit(data, command, parameter):
for it in commands_variables[command]:
if it in data['units']:
variable = it
else:
continue
unit = data['units'][variable]
conversion_factor = conversion_factors[unit]
if type(parameter) is float:
converted = parameter*conversion_factor
elif type(parameter) is list:
converted = [parameter[it]*conversion_factor
for it in range(len(parameter))]
elif type(parameter) is OrderedDict:
for key, value in parameter.items():
value = parameter[key]
converted = [value[it]*conversion_factor
for it in range(len(value))]
return converted
input_converted = {}
for key, value in input_processed.items():
input_converted[key] = convert_unit(input_processed, key, value)
所需的输出用于功能
9.81
[0.1, 0.2, 0.1]
{'po' : [0.0, 100000.0], 'muo' : [0.0327, 0.0327]}
0.05
和主程序
input_processed = {'units' : {'g' : 'g',
'dx' : 'cm',
'po' : 'bar',
'muo' : 'mPas'},
'g' : 9.81,
'dx' : [0.1, 0.2, 0.1],
'muo' : {'po' : [0.0, 100000.0],
'muo' : [0.0327, 0.0327]},
'phi' : 0.05}
我设法转换浮点数和列表但没有字典。在这个缩短的问题陈述中,我得到了局部变量'转换的错误。在分配之前引用。
如果某人有更简单的方法来转换数量,我将不胜感激。
答案 0 :(得分:0)
现有代码的主要问题是您的
for key, value in parameter.items():
循环没有在嵌套字典中累积更改的项目,因此代码的该部分生成的converted
将只是item
中转换的最后parameter
;此部分仅处理作为列表的嵌套字典项,它将在普通浮点数上失败。
FWIW,主return converted
循环底部的for
看起来有点可疑:循环内的无条件return
会导致函数在第一个循环结束时返回循环迭代。这真的很好,因为我们做想要在我们获得成功的匹配it in data['units']
之后退出循环,但是对于阅读代码的人来说它仍然有点棘手。 :)
一个小问题是使用type
进行类型测试。建议您改用isinstance
。有关详细信息,请参阅Differences between isinstance() and type() in python。正如答案中提到的那样,尽可能避免type
尽可能地检查Python,因为这会干扰鸭子打字。
无论如何,这是您的功能的修改版本。我的代码在Python 2.6.6上进行了测试,但它应该在Python 3上正确执行...我想。 :)
from pprint import pprint
conversion_factors = {
'g' : 9.81,
'cm' : 0.01,
'bar' : 10**5,
'mPas' : 10**-3
}
input_processed = {
'units' : {
'g' : 'g',
'dx' : 'cm',
'po' : 'bar',
'muo' : 'mPas'
},
'g' : 1.0,
'dx' : [10.0, 20.0, 10.0],
'muo' : {
'po' : [0.0, 1.0],
'muo' : [32.7, 32.7]
},
'phi' : 0.05
}
def convert_dict(indata):
units = indata['units']
def convert(key, item):
factor = conversion_factors.get(units.get(key))
if factor is not None:
if isinstance(item, list):
item = [u * factor for u in item]
else:
item *= factor
return item
outdata = {'units': units.copy()}
for k, v in indata.items():
if k == 'units':
continue
if isinstance(v, dict):
outdata[k] = newd = {}
for k1, v1 in v.items():
newd[k1] = convert(k1, v1)
else:
outdata[k] = convert(k, v)
return outdata
input_converted = convert_dict(input_processed)
pprint(input_converted)
<强>输出强>
{'dx': [0.10000000000000001, 0.20000000000000001, 0.10000000000000001],
'g': 9.8100000000000005,
'muo': {'muo': [0.032700000000000007, 0.032700000000000007],
'po': [0.0, 100000.0]},
'phi': 0.050000000000000003,
'units': {'dx': 'cm', 'g': 'g', 'muo': 'mPas', 'po': 'bar'}}
FWIW,虽然pprint.pprint
可以显示字典,但您可以使用json.dumps
获得更漂亮的输出。