当您发现自己在说“我想数数……”时,Counter()(来自 collections 模块)很有可能会提供帮助。
在这种情况下,我们想计算每个字母出现在多少个列表中。由于我们不想为每个子列表多次计算任何字母,我们将它们转换为sets:
>>> res = [['a', 'b', 'a'], ['a', 'b', 'c'], ['a']]
>>> [set(x) for x in res]
[{'b', 'a'}, {'c', 'b', 'a'}, {'a'}]
顺序会混淆,但这没关系,只要每个列表中只有一个字母即可。
现在我们想将这些字母组合成一个序列,这样我们就可以将它们全部计数。我们可以这样做:
>>> [s for x in res for s in set(x)]
['b', 'a', 'c', 'b', 'a', 'a']
...但这有点难以理解。幸运的是,itertools 模块中有一个名为chain() 的函数可以做同样的事情并且更容易阅读。我们想要chain.from_iterable() 版本:
>>> from itertools import chain
>>> c = chain.from_iterable(set(x) for x in res)
>>> list(c)
['b', 'a', 'c', 'b', 'a', 'a']
不要太担心list(c) - chain() 返回一个iterator,这意味着在我们对结果进行实际操作(比如将其放入列表)之前,什么都不会计算,所以我这样做了显示它产生了什么。
无论如何,我们现在需要做的就是将该序列传递给Counter():
>>> from collections import Counter
>>> Counter(chain.from_iterable(set(x) for x in res))
Counter({'a': 3, 'b': 2, 'c': 1})
这就是全部内容:
from collections import Counter
from itertools import chain
res = [['a', 'b', 'a'], ['a', 'b', 'c'], ['a']]
letter_count = Counter(chain.from_iterable(set(x) for x in res))
print(letter_count['a']) # prints 3