从字典中订购列表?

时间:2017-04-25 10:59:24

标签: python list dictionary

我有一本字典和一份清单

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 = 4a = 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方法来做同样的事情。

4 个答案:

答案 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方式,只是从你的代码中删除了一个循环。

  1. 我们在任何循环中使用相同的值执行相同的操作,然后将该操作移出循环。
  2. e.g。 par.split('_')[-1][0]计算在for循环中par值不变,将此类语句移到循环外。

    1. 无需迭代字典以检查密钥是否存在。 for p,val in dic.items():
    2. <强>演示:

      >>> 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}

警告:但这假设两者的长度相同,并且要排序的字母相同。