【问题标题】:Create a dictionary from list of dictionary with multiple repeated keys and to select max value from that list从具有多个重复键的字典列表中创建一个字典,并从该列表中选择最大值
【发布时间】:2018-11-29 18:45:14
【问题描述】:

我知道有很多与字典操作相关的帖子,但我找不到适合我的特殊情况的解决方案。 我有字典列表(具有相似或不同值的重复字典键),我必须从这个列表中创建一个新字典。 例如:

a = [{u'a': 1}, {u'a': 2}, {u'a': 1}, {u'b': 2}, {u'b': 1}, {u'c': 1}, {u'c': 1}]

我正在寻找的输出:

{'a': 2, 'b':2, 'c': 1}

如您所见,我只希望列表中的每个键都有一个条目,并且该键的值将是所有值的最大值。希望它不会太混乱。 我有一个工作灵魂,但我只是想检查是否有更多的pythonic答案(用更少的#of行或更好的方法) 这是我的工作解决方案:

d = {}
for i in a:
    if not d.get(i.keys()[0]):
        d.update(i)
    elif d.get(i.keys()[0], 0) < i.values()[0]:
        d.update(i)
print d

感谢您的宝贵时间。

【问题讨论】:

    标签: python python-2.7 dictionary


    【解决方案1】:

    您可以对列表a 进行排序,这样类似的键就是组,最大值排在最后。然后添加值,使最后一个值是字典中留下的值:

    >>> a = [{u'a': 1}, {u'a': 2}, {u'a': 1}, {u'b': 2}, {u'b': 1}, {u'c': 1}, {u'c': 1}]
    >>> {k:v for k,v in (x.items()[0] for x in sorted(a))}
    {u'a': 2, u'c': 1, u'b': 2}
    

    或者,替代语法:

    >>> dict(x.items()[0] for x in sorted(a))
    

    对于 Python 2 和 3 语法:

    >>> {k:v for k,v in (sorted(list(x.items())[0] for x in a))}
    {'a': 2, 'b': 2, 'c': 1}
    >>> dict(sorted(list(x.items())[0] for x in a))
    {'a': 2, 'b': 2, 'c': 1}
    

    来自 cmets:这里发生了什么?

    首先,让我们举一个更有启发性的例子:

    >>> a = [{u'a': -1}, {u'a': -11}, {u'a': -3}, {u'b': 0}, {u'b': 100}, {u'c': 3}, {u'c': 1}]
    

    因此,此处所需的结果是键(对于在 dict 或使用 OrderedDict 中保持顺序的 Python 3)将是 i) 排序值组中的键,然后 ii) 值被解释为递增值中的数字。

    所以先试试这个:

    >>> sorted(list(x.items())[0] for x in a)
    [('a', -11), ('a', -3), ('a', -1), ('b', 0), ('b', 100), ('c', 1), ('c', 3)]
    

    分开:

    sorted(list(x.items())[0] for x in a)
           ^                            ^ comprehension of
                                     ^  a list of one element dicts
             ^       ^     ^            convert to a two element tuple
      ^                                 sort the tuple first by key, then by value
    

    因此,首先按键对元组进行排序,然后按值对元组进行排序。

    这导致使用groupby 的替代解决方案:

    >>> from itertools import groupby
    >>> for k,v in groupby(sorted(list(x.items())[0] for x in a), key=lambda t: t[0]):
    ...     print(k, max(v))
    ... 
    a ('a', -1)
    b ('b', 100)
    c ('c', 3)
    

    groupby 解决方案对内存更友好,因为它不会创建额外的列表。第一个解决方案可能会使用较小的 dicts 列表更快,因为排序更容易(但您需要对其进行测试。)

    在我给出的解决方案中需要将密钥分组(groupby 需要它才能工作)。这也有效:

     >>> sorted((list(x.items())[0] for x in a), key=lambda t: t[1])
     [('a', -11), ('a', -3), ('a', -1), ('b', 0), ('c', 1), ('c', 3), ('b', 100)]
    

    然后用dict构造函数把它变成dict。回忆一下采用(key, value) 的元组列表:

    >>> dict(sorted((list(x.items())[0] for x in a), key=lambda t: t[1]))
    {'a': -1, 'b': 100, 'c': 3}
    

    【讨论】:

    • 这也是完成这项任务的最快方法。恭喜你。
    • @FilipMłynarski:已编辑。谢谢
    • @dawg 感谢 sol,我想到了这种方法,但不确定如何实现字典的排序列表(按值然后按键)。其实我还是一头雾水。如果将 dict 传递给 sorted(),它将按其键排序。这里发生了什么事?在字典列表中。您能否解释或指出任何参考文档。
    【解决方案2】:

    你可以这样做:

    a = [{u'a': 1}, {u'a': 2}, {u'a': 1}, {u'b': 2}, {u'b': 1}, {u'c': 1}, {u'c': 1}]
    
    result = {}
    for di in a:
        for key, value in di.items():
            result[key] = max(value, result.get(key, value))
    print(result)
    

    输出

    {'a': 2, 'c': 1, 'b': 2}
    

    【讨论】:

      【解决方案3】:

      你可以使用defaultdict:

      from collections import defaultdict
      
      d = defaultdict(lambda: 0)
      for val in a:
          if d[val.keys()[0]] < val.values()[0]:
              d[val.keys()[0]] = val.values()[0]
      

      输出

      {u'a': 2, u'b': 2, u'c': 1}
      

      【讨论】:

        【解决方案4】:

        如果给定键不在新字典中或其值低于原始值,您可以遍历所有字典并使用其内容更新最终字典 new_a

        a = [{u'a': 1}, {u'a': 2}, {u'a': 1}, {u'b': 2}, {u'b': 1}, {u'c': 1}, {u'c': 1}]
        new_a = {}
        
        for dict_ in a:
            key, value = list(dict_.items())[0]
            if key not in new_a or new_a[key] < value:
                new_a[key] = value
        
        print(new_a) # -> {'c': 1, 'b': 2, 'a': 2}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-09-04
          • 1970-01-01
          • 1970-01-01
          • 2018-08-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-25
          相关资源
          最近更新 更多