如何获取具有特定元素的列表的数量?

How do I get the number of lists with a particular element?

我有一个列表列表,看起来像

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:

的生成器理解
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 并将每个列表转换为一个集合。 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})

如果您喜欢函数式编程,您还可以将 chainset-mapped 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

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 的计算移到字典理解

中来使其成为 one-liner

这是另一个使用循环的版本:

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 添加到该键的值。