Python 如何获取具有特定元素的列表的数量?
我有一个列表,看起来像Python 如何获取具有特定元素的列表的数量?,python,list,python-3.x,counting,Python,List,Python 3.x,Counting,我有一个列表,看起来像 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_t
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}
我想知道是否有更好的方法来实现我的目标。我会将每个列表转换为一组,然后在传递给
计数器的生成器中进行计数:
import collections
print(collections.Counter(y for x in listOfLists for y in set(x)))
>>> 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({'a': 3, 'c': 3, 'b': 2, 'd': 1})
(这实际上就是您所做的,但是上面的代码缩短了许多循环和临时列表创建)使用a并将每个列表转换为一个集合。集合
将从每个列表中删除任何重复项,这样您就不会对同一列表中的重复值进行计数:
>>> from collections import Counter
>>> Counter(item for lst in listOfLists for item in set(lst))
Counter({'a': 3, 'b': 2, 'c': 3, 'd': 1})
如果您喜欢函数式编程,还可以将集合的链
-映射
ped列表
馈送到计数器
:
import collections
print(collections.Counter(y for x in listOfLists for y in set(x)))
>>> from collections import Counter
>>> from itertools import chain
>>> Counter(chain.from_iterable(map(set, listOfLists)))
Counter({'a': 3, 'b': 2, 'c': 3, 'd': 1})
这与第一种方法完全相同(除了可能快一点之外)。您也可以在不使用计数器的情况下执行此操作:
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(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\u iterable
展平,然后送入计数器
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))))
这种方法使用集合理解计算列表中的唯一条目,然后使用字典理解计算每个列表中的出现次数
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 = {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}
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
因此,创建一个名为final的空字典。然后循环浏览每个列表的每个字母。创建一个新键,如果字母还没有作为键存在于final中,则值=1。否则,为该键的值添加1。无需再次将集合A
强制转换为列表,也无需向集合提供列表理解,生成表达式更好。。。实际上,您可以将A
构建为一个集合too@Copperfield谢谢你的建议。我做了一个改变。我在CPython 2.7.11上使用itertools.chain
(~40%!)获得了更快的执行速度。不过,计数器
+itertools.chain
执行速度比我介绍的raw
方法慢4倍。@zwer-Eh,取决于我们讨论的输入大小。我的解决方案有更多的开销,但如果您增加输入大小,它会更快。这就是为什么基准测试并不太重要:)没错,我只是对我所在的位置在速度上的巨大差异感到惊讶,我不习惯itertools
实际上比任何东西都好——它们通常是速度较慢但更容易阅读的选择:D