【问题标题】:Union of all keys from a list of dictionaries字典列表中所有键的联合
【发布时间】:2013-06-03 17:31:03
【问题描述】:

假设我有一个字典列表。它们在每一行中大多具有相同的键,但有一些不匹配并且具有额外的键/值对。有没有一种快速的方法来获取所有行中的所有键?

现在我正在使用这个循环:

def get_all_keys(dictlist):
    keys = set()
    for row in dictlist:
        keys = keys.union(row.keys())

在包含数十万行的列表上执行此操作似乎非常低效,但我不确定如何做得更好

谢谢!

【问题讨论】:

  • set([row.keys() for row in dictlist]) 不是您想要的。此外,它会导致TypeError
  • 你说得对,我还没有真正尝试过。

标签: python list dictionary


【解决方案1】:

你可以试试:

def all_keys(dictlist):
    return set().union(*dictlist)

避免导入,并将充分利用set 的底层实现。也适用于任何可迭代的东西。

【讨论】:

  • 谢谢!这行得通,但我不知道为什么。您能帮我理解星号在这种情况下的作用吗?怎么只提取dictlist的key?
  • 当然...* 将列表解压缩为set.union 的单独参数,它可以采用任意数量的可迭代参数...(因此上述调用实际上是 set().union( first_dict, second_dict,third_dict,fourth_dict...) 所以对于列表中的每个对象,它都会尝试迭代它(在 dict 的情况下是它的键,或者一个列表/元组它的项目,或者对于一个字符串它的字符......等等......)
  • 啊,谢谢。这也有助于我理解星号的用途。
【解决方案2】:

在 python3.x1 上运行的一个有趣的依赖于 reduce 并且 dict.keys() 现在返回一个类似集合的对象:

>>> from functools import reduce
>>> dicts = [{1:2},{3:4},{5:6}]
>>> reduce(lambda x,y:x | y.keys(),dicts,{})
{1, 3, 5}

物有所值,

>>> reduce(lambda x,y:x | y.keys(),dicts,set())
{1, 3, 5}

也可以,或者,如果您想避免 lambda(和初始化程序),您甚至可以这样做:

>>> reduce(operator.or_, (d.keys() for d in dicts))

非常整洁。

当你只有两个元素时,这真的最闪耀。然后,您可以使用a.keys() | b.keys() 代替set(a) | set(b) 之类的操作,这对我来说似乎更好一些。


1它也可以在python2.7上工作。使用dict.viewkeys 而不是dict.keys

【讨论】:

  • 不相信您需要方法调用... reduce(set.union, dicts, set()) 我相信应该可以工作...
  • @JonClements -- 是的。我的想法是更多地展示python3.x中dict.keys的集合性质
  • 嗯,好吧 - reduce(operator.or_, (d.keys() for d in dicts)) ?
  • @JonClements -- 是的,我喜欢那个。我将使用它进行更新。
【解决方案3】:

你可以这样做:

from itertools import chain
return set(chain.from_iterable(dictlist))

正如@Jon Clements 所指出的,这与将* 运算符用于chainunion 相比,只能将所需的数据保留在内存中。

【讨论】:

  • chain 在这里做什么?
  • 那行不通——它会尝试从每个字典中创建一个集合。你需要set(chain.from_iterable(dictlist)) 或其他东西。
  • 我会选择@DSM - 绝对是chain.from_iterable - 它基本上是chain(*dictlist),但更优化(恕我直言,更明确一点)......
  • @JonClements,我在这里看不到chain.from_iterable 的优势。由于 dicts 和 dictlist 都已经存在,所以没有保存。
  • @gnibbler dictlist 可以是任何可迭代的。不仅仅是一个列表。
【解决方案4】:

sets 就像字典一样,并且有一个 update() 方法,所以这将在您的循环中起作用:

keys.update(row.iterkeys())

【讨论】:

    【解决方案5】:

    如果您担心性能,您应该退出dict.keys() 方法,因为它会在内存中创建一个列表。而且可以用set.update()代替union,不知道是不是比set.union()快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-21
      • 2014-11-27
      • 2022-12-18
      相关资源
      最近更新 更多