如何获得特定元素的列表数量?
我有一个列表的列表,它看起来像如何获得特定元素的列表数量?
listOfLists = [
['a','b','c','d'],
['a','b'],
['a','c'],
['c','c','c','c']
]
我想指望它有一个特定的元素列表的数量。例如,我的输出应该是
{'a':3,'b':2,'c':3,'d':1}
正如你所看到的,我不需要一个元素的总数。在"c"
的情况下,虽然其总数为5,但输出为3,因为它仅出现在3个列表中。
我正在使用计数器来计数。下面可以看到同样的情况。
line_count_tags = []
for lists in lists_of_lists:
s = set()
for element in lists:
s.add(t)
lines_count_tags.append(list(s))
count = Counter([count for counts in lines_count_tags for count in counts])
所以,当我打印数量,我得到
{'a':3,'c':3,'b':2,'d':1}
我想知道如果有一个更好的方式来完成我的目标。
使用一个Counter
并将每个列表转换为一个集合。该set
将从每个列表中删除任何重复,这样你就不会在同一个列表统计重复值:
>>> from collections import Counter
>>> Counter(item for lst in listOfLists for item in set(lst))
Counter({'a': 3, 'b': 2, 'c': 3, 'd': 1})
如果你喜欢函数式编程也可以养活chain
set
的 - map
PED listOfLists
到Counter
:
>>> from collections import Counter
>>> from itertools import chain
>>> Counter(chain.from_iterable(map(set, listOfLists)))
Counter({'a': 3, 'b': 2, 'c': 3, 'd': 1})
这与第一种方法完全相同(除了可能稍微快一点)。
我想每一个列表转换为一组在发电机理解计数前传递给Counter
:
import collections
print(collections.Counter(y for x in listOfLists for y in set(x)))
结果:
Counter({'a': 3, 'c': 3, 'b': 2, 'd': 1})
(这实际上是你做了什么,但上面的代码短裤很多循环和临时列表创建)
你可以不用一个Counter
,太:
result = {}
for lis in listOfLists:
for element in set(lis):
result[element] = result.get(element, 0) + 1
print result # {'a': 3, 'c': 3, 'b': 2, 'd': 1}
不是最优雅的,更应该是相当快的。
在Counter
方法与itertools.chain.from_iterable
文体差异的一点可能看起来像
Counter(chain.from_iterable(map(set, listOfLists)))
演示
>>> from itertools import chain
>>> from collections import Counter
>>> Counter(chain.from_iterable(map(set, listOfLists)))
Counter({'a': 3, 'b': 2, 'c': 3, 'd': 1})
粗略的基准
%timeit Counter(item for lst in listOfLists for item in set(lst))
100000 loops, best of 3: 13.5 µs per loop
%timeit Counter(chain.from_iterable(map(set, listOfLists)))
100000 loops, best of 3: 12.4 µs per loop
只需转换为set
,使用itertools.chain.from_iterable
展平,然后输入Counter
即可。
from collections import Counter
from itertools import chain
inp = [
['a','b','c','d'],
['a','b'],
['a','c'],
['c','c','c','c']
]
print(Counter(chain.from_iterable(map(set, inp))))
这种方法使用一套理解计算独特的条目listOfLists
,然后使用字典解析
A = {val for s in listOfLists for val in s}
d = {i: sum(i in j for j in listOfLists) for i in A}
print(d) # {'a': 3, 'c': 3, 'b': 2, 'd': 1}
我承认这是一个有点难看计算每单出现,但它是一个可能的解决方案(和字典理解的一个很酷的使用)。 您还可以通过移动A
计算对入字典解析
不需要再次将您的集合'A'转换为列表或者以列表理解的形式提供集合,生成表达式更好......实际上您可以构建'A '也作为一种理解 – Copperfield
@Copperfield感谢您的建议。我做了一个改变。 – nbryans
这里做这一个班轮是使用循环另一个版本:
listOfLists = [
['a','b','c','d'],
['a','b'],
['a','c'],
['c','c','c','c']
]
final = {}
for lst in listOfLists:
for letter in lst:
if letter in final:
final[letter] += 1
else:
final[letter] = 1
所以创建一个名为最后一个空的字典。然后遍历每个列表的每个字母。如果该字母在最终还不存在作为关键字,则创建一个新的关键字和值= 1。否则,加1到该键的值。
我在CPython 2.7.11上使用'itertools.chain'(〜40%!)获得更快的执行速度。尽管如此,'Counter' +'itertools.chain'的执行速度比我提出的'raw'方法慢4倍。 – zwer
@zwer Eh,取决于我们正在讨论的输入大小。我的解决方案有更多的开销,但如果您增加输入大小,它应该更快。这就是为什么基准测试不是太重要:) – miradulo
的确如此,我只是对我的位置在速度方面的巨大差异感到惊讶,我不习惯“itertools”实际上表现超越,几乎任何东西 - 它们都是通常是较慢的,但更易于阅读的选择:D – zwer