我有一本字典和一份清单
dic = {'J': 5, 'a': 1, 'b': 2, 'c': 3, 'r': 4}
Lpars = ['dm_a', 'dm_b', 'J', 'dm_r0', 'dm_c']
我想创建一个新词典(或元组),将dic
中的值分配给包含该键的Lpars
条目。例如,dm_r0 = 4
,a = 1
等等。
我用
实现了这个目标new_vals = []
for par in Lpars:
for p,val in dic.items():
if p in par.split('_')[-1]:
new_vals.append((par,val))
或等效地使用以下列表理解:
new_vals = [(par,val) for par in Lpars for p, val in dic.items() if p in par.split('_')[-1]]
我想知道是否有人能想到一个漂亮,干净和紧凑的Pythonic方法来做同样的事情。
答案 0 :(得分:1)
如果您假设所有键都是单个字符,则可以避免在字典上嵌套循环并直接查找键:
split = ((par, par.split('_')[-1]) for par in Lpars)
# list of tuples
[(par, dic[char]) for par, key in split for char in key if char in dic]
# dictionary
{par: dic[char] for par, key in split for char in key if char in dic}
我使用了一个单独的生成器表达式,使分割键可以在两个位置重复使用。以上产生的输出为O(Nk)时间(N是Lpars
中的项目数,k是_
之后的平均字符数),而不是O(NK)时间(您的解决方案) ,K是字典中的项目数)。由于k
远小于K
(实际上接近1),因此上述速度会更快,尤其是对于较大的输入数据。
如果只有第一个字符匹配,则可以完全消除分裂部分字符的循环:
split = ((par, par.split('_')[-1][0]) for par in Lpars)
{par: dic[key] for par, key in split if key in dic}
如果密钥保证在字典中,您可以完全删除if key in dic
部分:
split = ((par, par.split('_')[-1][0]) for par in Lpars)
{par: dic[key] for par, key in split}
第一个选项的演示(不存在关于第一个字符或键存在的假设):
>>> dic = {'J': 5, 'a': 1, 'b': 2, 'c': 3, 'r': 4}
>>> Lpars = ['dm_a', 'dm_b', 'J', 'dm_r0', 'dm_c']
>>> split = ((par, par.split('_')[-1]) for par in Lpars)
>>> [(par, dic[char]) for par, key in split for char in key if char in dic]
[('dm_a', 1), ('dm_b', 2), ('J', 5), ('dm_r0', 4), ('dm_c', 3)]
>>> split = ((par, par.split('_')[-1]) for par in Lpars)
>>> {par: dic[char] for par, key in split for char in key if char in dic}
{'dm_a': 1, 'dm_b': 2, 'J': 5, 'dm_r0': 4, 'dm_c': 3}
答案 1 :(得分:0)
试试这个:
result : {'J': 5, 'dm_a': 1, 'dm_b': 2, 'dm_c': 3, 'dm_r0': 4}
它产生了这个结果:
document.getElementById('message').innerHTML = "id:" + car1.id + " - type " + car1.type
//Return id:1346 - type BMW
答案 2 :(得分:0)
我没有给出智能的pythonic方式,只是从你的代码中删除了一个循环。
e.g。 par.split('_')[-1][0]
计算在for
循环中par
值不变,将此类语句移到循环外。
for p,val in dic.items():
<强>演示:强>
>>> map_dict = {'J': 5, 'a': 1, 'b': 2, 'c': 3, 'r': 4}
>>> input_pars = ['dm_a', 'dm_b', 'J', 'dm_r0', 'dm_c']
>>>
>>> result = []
>>> for par in input_pars:
... character = par.split('_')[-1][0]
... if character in map_dict:
... result.append((par, map_dict[character]))
...
>>> result
[('dm_a', 1), ('dm_b', 2), ('J', 5), ('dm_r0', 4), ('dm_c', 3)]
如果我们想检查para_characters是否在字典键中,那么使用break
语句来避免不必要的迭代。
<强>演示:强>
>>> map_dict = {'J': 5, 'a': 1, 'b': 2, 'c': 3, 'r': 4}
>>> input_pars = ['dm_a', 'dm_b', 'J', 'dm_r0', 'dm_c']
>>>
>>> result = []
>>> for par in input_pars:
... characters = par.split('_')[-1]
... for key in map_dict:
... if key in characters:
... result.append((par, map_dict[character]))
... break
...
>>>
>>> result
[('dm_a', 3), ('dm_b', 3), ('J', 3), ('dm_r0', 3), ('dm_c', 3)]
>>>
答案 3 :(得分:-1)
这个怎么样?
from collections import OrderedDict
dict(zip(sorted(Lpars), OrderedDict(sorted(dic.items(), key=lambda x: x[0])).values()))
>>> {'J': 5, 'dm_a': 1, 'dm_b': 2, 'dm_c': 3, 'dm_r0': 4}
警告:但这假设两者的长度相同,并且要排序的字母相同。