我有一个元组列表,如下所示。我必须计算有多少项目的数字大于 1。到目前为止我编写的代码非常慢。即使有大约 10K 的元组,如果你看到下面的示例字符串出现两次,那么我必须得到这样的字符串。我的问题是通过迭代生成器来实现字符串计数的最佳方法是什么
列表:
b_data=[('example',123),('example-one',456),('example',987),.....]
到目前为止我的代码:
blockslst=[]
for line in b_data:
blockslst.append(line[0])
blocklstgtone=[]
for item in blockslst:
if(blockslst.count(item)>1):
blocklstgtone.append(item)
原文由 min2bro 发布,翻译遵循 CC BY-SA 4.0 许可协议
从每个元组中提取第一项的想法是正确的。您可以使用列表/生成器理解使您的代码更简洁,如下所示。
从那时起,查找元素频率计数的最惯用方式是使用
collections.Counter
对象。Counter
example
当然,您可以使用
list.count
如果您只想查找 其中 一项的频率计数,但在一般情况下,Counter
是最佳选择。Counter
的优点是它以线性 (O(N)
) 时间执行 所有 元素的频率计数(不仅仅是example
)。假设您还想查询另一个元素的计数,比如foo
。那将完成 -如果列表中不存在
'foo'
0
,则返回—。如果你想找到最常见的元素,调用
counts.most_common
其中
n
是您要显示的元素数。如果您想查看所有内容,请不要通过n
。要检索最常见元素的计数,一种有效的方法是查询
most_common
,然后使用itertools
高效地提取所有计数超过 1 的元素。(OP 编辑)或者,使用 列表理解 来获取计数 > 1 的项目列表 -
请记住,这不如
itertools.takewhile
解决方案有效。例如,如果你有一个计数 > 1 的项目,以及一百万个计数等于 1 的项目,你最终会迭代列表一百万零一次,而你不必这样做(因为most_common
按降序返回频率计数)。使用takewhile
情况并非如此,因为一旦 count > 1 的条件变为假,您就会停止迭代。