【问题标题】:Find common keys of a number of dictionaries查找多个字典的公共键
【发布时间】:2015-10-10 01:44:44
【问题描述】:

我有大约 20000 个字典。我想找到所有字典中通用的所有键(该键需要存在于所有 20000 个字典中)。我怎样才能做到这一点。目前我正在写类似的东西,但是它没有给我想要的结果:

if parsedData.keys() not in uniquelist: 
            uniquelist.append(parsedData.keys())
        else:
            commonlist.append(parsedData.keys())

这里解析的数据是我的字典。请帮我解决这个问题。

【问题讨论】:

  • parsedData 是什么样的?它包含你所有的字典文件吗?

标签: python dictionary


【解决方案1】:

您可以在第一个字典中创建一组键,然后在循环中与其余键形成交集:

>>> d1 = {'a':1, 'b':2, 'c':3}
>>> d2 = {'b':4, 'c':7,'d':5}
>>> d3 = {'b':5, 'c':8,'e':6}
>>> dicts = [d1,d2,d3]
>>> common_keys = set(d1.keys())
>>> for d in dicts[1:]:
    common_keys.intersection_update(set(d.keys()))

>>> common_keys
{'b', 'c'}

【讨论】:

  • 如果我不沉迷于理解,这就是我会做的事情。我的解决方案基本上做到了这一点,但在一个班轮中。诚然,这更容易理解。
【解决方案2】:

我会使用collections 模块中的Counter 例如:

from collections import Counter
count = Counter()
for dictionary in listOfAllDictionaries:
    count = count+Counter(dictionary)
uniquelist = [key for key in count if count[key] == 1]
commonlist = [key for key in count if count[key] > 1]

【讨论】:

  • 我不会使用 Counter,只是为了测试存在的开销很大。
  • 看起来他既想要独特的元素,也想要共同的元素。 sets 的解决方案似乎忽略了这一点。
  • 虽然你可能是对的:他确实只要求共同的元素。
  • 他只要求共同点,但我会编辑我的答案以做到独一无二。我再次认为集合是最有效的。
【解决方案3】:

这可能不是最有效的方法,但它只使用常见的、易于理解的运算符和方法。只需创建所有键的列表,并计算出现次数与您的字典一样多的键

>>> d1 = {1: 'a', 2: 'b'}
>>> d2 = {3: 'c', 2: 'b'}
>>> dictionaries = [d1, d2]
>>> for d in dictionaries:
    keys += list(d.keys())

>>> keys
[1, 2, 2, 3]

>>> commonkeys = []
>>> for k in keys:
    if k not in commonkeys and keys.count(k) == len(dictionaries):
        commonkeys += [k]

>>> commonkeys
[2]

瞧,字典之间的公共键是 2。

【讨论】:

  • 这行得通,但是对于他拥有的这么多字典,您不必存储可能很大的非唯一键列表。我认为这是使用集合的出租解决方案
  • 同意。使用集合要快两个数量级。
【解决方案4】:

捏约翰科尔曼的example dictionaries

d1 = {'a':1, 'b':2, 'c':3}
d2 = {'b':4, 'c':7,'d':5}
d3 = {'b':5, 'c':8,'e':6}
d = [d1, d2, d3]
d = iter(d)
reduce(set.intersection, d, set(next(d)))
set(['c', 'b'])

【讨论】:

    【解决方案5】:

    一种 Pythonic 方式,不一定是最容易理解的。尽管如此,这里是一个班轮:

    >>> d1 = { 'a' : 1, 'b' : 1 }
    >>> d2 = { 'a' : 1, }
    >>> d3 = { 'a' : 1, 'c' : 1 }
    >>> set.intersection(*tuple(set(d.keys()) for d in [d1, d2, d3]))
    
    set(['a'])
    

    与使用 Counters 和 Lists 的解决方案不同,这应该非常有效,并且通过这么多 dicts 的开销很低。但是,这确实构建了一个大元组,因此,我怀疑更有效的代码是循环遍历它。

    有人提到您可能还需要“唯一”键,但我不确定是什么意思。这是否意味着,只是不常见,或者这意味着,只有一个字典?如果是前者,那么也只保留一个集合,即并集,而不是交集,然后在完成后取两者的差。根据我们所说的唯一键的总数,我仍然认为这是一个相对便宜的操作。

    编辑: 回答以下问题:

    from collections import defaultdict
    
    all_dicts = [d1, d2, d3]
    common = set.intersection(*tuple(set(d.keys()) for d in all_dicts))
    
    common_key_values = defaultdict(list)
    for d in all_dicts:
        for key in common:
            common_key_values.append(d[key])
    

    【讨论】:

    • 非常感谢,它的工作方式与我想要的完全一样。
    • 如果我想从每个字典中检索公共键的所有值,我应该如何操作代码?
    • 我会编辑我的答案,但以后会很好并奖励答案,然后提出一个新问题。
    猜你喜欢
    • 2012-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多