【问题标题】:Intersection of subelements of multiple list of lists in dictionary字典中多个列表的子元素的交集
【发布时间】:2015-01-26 05:53:02
【问题描述】:

我有许多存储在字典中的列表。我想找到子列表的交集(即intersection of dict[i][j]) for all keys of the dictionary。)

例如,如果字典改为存储元组集,我可以使用以下代码:

set.intersection(*[index[key] for key in all_keys]) 

什么是执行此操作的有效方法?我尝试的一种方法是首先将每个列表列表转换为一组元组,然后取它们的交集,但这相当笨拙。

例子:

假设列表列表的字典是

dict = {} 
dict['A'] = [[1, 'charlie'], [2, 'frankie']] 
dict['B'] = [[1, 'charlie'], [2, 'chuck']]
dict['C'] = [[2, 'chuck'], [1, 'charlie']]

那我想退货

[1, 'charlie']

(可以是元组,不一定是列表)

编辑:我刚刚找到了一个不错的方法,但它不是很“pythonic”

def search(index, search_words): 
    rv = {tuple(t) for t in index[search_words[0]]}
    for word in search_words: 
        rv = rv.intersection({tuple(t) for t in index[word]})
    return rv 

【问题讨论】:

  • 你能给个样品吗?
  • 是的!刚加了一个——谢谢
  • 哪里有字典?问题标题说字典
  • A、B 和 C 存储在字典中。我会编辑清楚

标签: python list set


【解决方案1】:

让我们将您的列表字典称为d

>>> d = {'A': [[1, 'charlie'], [2, 'frankie']], 'B': [[1, 'charlie'], [2, 'chuck']], 'C': [[2, 'chuck'], [1, 'charlie']]}

我称它为d,因为dict 是内置的,我们不希望覆盖它。

现在,找到交点:

>>> set.intersection( *[ set(tuple(x) for x in d[k]) for k in d ] )
set([(1, 'charlie')])

工作原理

  • set(tuple(x) for x in d[k])

    对于键k,这形成了一个由d[k] 中元素的元组组成的集合。以k='A' 为例:

    >>> k='A'; set(tuple(x) for x in d[k])
    set([(2, 'frankie'), (1, 'charlie')])
    
  • [ set(tuple(x) for x in d[k]) for k in d ]

    这会列出上述步骤中的集合。因此:

    >>> [ set(tuple(x) for x in d[k]) for k in d ]
    [set([(2, 'frankie'), (1, 'charlie')]),
     set([(2, 'chuck'), (1, 'charlie')]),
     set([(2, 'chuck'), (1, 'charlie')])]
    
  • set.intersection( *[ set(tuple(x) for x in d[k]) for k in d ] )

    这收集了上述三个集合的交集:

    >>>set.intersection( *[ set(tuple(x) for x in d[k]) for k in d ] )
    set([(1, 'charlie')])
    

【讨论】:

  • 太棒了,正是我需要的。我尝试做类似的事情一段时间,但我的符号一定是关闭了。谢谢!
【解决方案2】:
[item for item in A if item in B+C]

【讨论】:

  • 会有不同数量的列表,它们存储在字典中。
  • 每个列表可以只有一次,还是单个列表可以有冗余?
  • 这是个好问题。我很确定每个列表只会包含一次该项目......但它是抓取的数据,所以我不确定我是否会相信这个假设。
  • 因为如果是这样的话,你可以添加所有三个列表,然后我们 collections.count 看看哪个有三个。
【解决方案3】:

您的用例需要使用reduce 函数。但是,引用BDFL's take on reduce

所以现在reduce()。这实际上是我一直最讨厌的一个,因为除了涉及+* 的几个示例之外,几乎每次我看到带有非平凡函数参数的reduce() 调用时,我都需要抓住在我理解 reduce() 应该做什么之前,用笔和纸画出实际输入该函数的内容。所以在我看来,reduce() 的适用性几乎仅限于关联运算符,在所有其他情况下,最好明确地写出累积循环。

那么,你得到的已经是'pythonic'了。

我会这样写程序

>>> d = {'A': [[1, 'charlie'], [2, 'frankie']],
... 'B': [[1, 'charlie'], [2, 'chuck']],
... 'C': [[2, 'chuck'], [1, 'charlie']]}
>>> values = (value for value in d.values())
>>> result = {tuple(item) for item in next(values)}
>>> for item in values:
...    result &= frozenset(tuple(items) for items in item)
>>> result
set([(1, 'charlie')])

【讨论】:

    【解决方案4】:
    from collections import defaultdict    
    d = {'A': [[1, 'charlie'], [2, 'frankie']], 'B': [[1, 'charlie'], [2, 'chuck']], 'C': [[2, 'chuck'], [1, 'charlie']]}
    
    frequency = defaultdict(set)
    for key, items in d.iteritems():
        for pair in items:
            frequency[tuple(pair)].add(key)
    output = [
        pair for pair, occurrances in frequency.iteritems() if len(d) == len(occurrances)
    ]
    print output
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-06
      • 1970-01-01
      • 1970-01-01
      • 2019-09-07
      • 2020-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多