我有一个奇怪的问题,我需要找到重复的项目集合,其中订单无关紧要,但集合中存在重复值确实很重要。例如,假设我有以下列表列表:
lol = [
['red'],
['blue', 'orange'],
['orange', 'red'],
['red', 'orange'],
['red', 'red'],
['blue', 'orange', 'red'],
['red', 'orange', 'blue']
]
在我的情况下,唯一的集合将是:
unique_lol = [
['red'],
['blue', 'orange'],
['orange', 'red'],
['red', 'red'],
['blue', 'orange', 'red']
]
我想要获取的信息是重复列表:
dup_lol = [
['orange', 'red'],
['blue', 'orange', 'red']
]
我不关心哪个副本被报告为副本,即['orange', 'red']
vs ['red', 'orange']
,只是报告了重复的组合。我首先尝试使用一组frozensets:
sofs = {frozenset(x) for x in lol}
但是,这种方法会被['red', 'red']
列表绊倒,该列表会转换为['red']
:
set([frozenset(['red']),
frozenset(['orange', 'red']),
frozenset(['blue', 'orange', 'red']),
frozenset(['blue', 'orange'])])
另外,这不会给我重复,只有独特的重复,无论如何我都无法对列表列表产生差异。
我确信我可以迭代父级列表暴力风格,但我觉得我错过了一些简单的东西。我几乎需要一个字典,其中键是有序列表,值是组合出现的次数,但列表不能是字典键,而且听起来很奇怪。
答案 0 :(得分:7)
我认为你要找的是Counter。对每个条目进行排序,然后将其转换为元组,以便进行比较。计数器将跟踪每个唯一条目的计数:
>>> from collections import Counter
>>> counted = Counter(tuple(sorted(entry)) for entry in lol)
>>> import pprint
>>> pprint.pprint(dict(counted))
{('blue', 'orange'): 1,
('blue', 'orange', 'red'): 2,
('orange', 'red'): 2,
('red',): 1,
('red', 'red'): 1}
答案 1 :(得分:2)
如果内部列表中的项目顺序通常无关紧要,我会用计数器替换它们。
>>> lol = [
... ['red'],
... ['blue', 'orange'],
... ['orange', 'red'],
... ['red', 'orange'],
... ['red', 'red'],
... ['blue', 'orange', 'red'],
... ['red', 'orange', 'blue']
... ]
>>> from collections import Counter
>>> from pprint import pprint
>>> counters = [Counter(x) for x in lol]
>>> pprint(counters)
[Counter({'red': 1}),
Counter({'orange': 1, 'blue': 1}),
Counter({'red': 1, 'orange': 1}),
Counter({'red': 1, 'orange': 1}),
Counter({'red': 2}),
Counter({'orange': 1, 'red': 1, 'blue': 1}),
Counter({'blue': 1, 'red': 1, 'orange': 1})]
要计算计数器,我们需要先将它们转换为可以清除的东西:frozensets of(key,value)-tuples。
>>> counts = Counter(frozenset(c.iteritems()) for c in counters)
>>> pprint(counts)
{frozenset({('red', 1)}): 1,
frozenset({('orange', 1), ('red', 1)}): 2,
frozenset({('blue', 1), ('orange', 1)}): 1,
frozenset({('blue', 1), ('orange', 1), ('red', 1)}): 2,
frozenset({('red', 2)}): 1}