计算元组列表中项目的频率

新手上路,请多包涵

我有一个元组列表,如下所示。我必须计算有多少项目的数字大于 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 许可协议

阅读 509
2 个回答

从每个元组中提取第一项的想法是正确的。您可以使用列表/生成器理解使您的代码更简洁,如下所示。

从那时起,查找元素频率计数的最惯用方式是使用 collections.Counter 对象。

  1. 从元组列表中提取第一个元素(使用理解)
  2. 将此传递给 Counter
  3. 查询计数 example
 from collections import Counter

counts = Counter(x[0] for x in b_data)
print(counts['example'])

当然,您可以使用 list.count 如果您只想查找 其中 一项的频率计数,但在一般情况下, Counter 是最佳选择。


Counter 的优点是它以线性 ( O(N) ) 时间执行 所有 元素的频率计数(不仅仅是 example )。假设您还想查询另一个元素的计数,比如 foo 。那将完成 -

 print(counts['foo'])

如果列表中不存在 'foo' 0 ,则返回—。

如果你想找到最常见的元素,调用 counts.most_common

 print(counts.most_common(n))

其中 n 是您要显示的元素数。如果您想查看所有内容,请不要通过 n


要检索最常见元素的计数,一种有效的方法是查询 most_common ,然后使用 itertools 高效地提取所有计数超过 1 的元素。

 from itertools import takewhile

l = [1, 1, 2, 2, 3, 3, 1, 1, 5, 4, 6, 7, 7, 8, 3, 3, 2, 1]
c = Counter(l)

list(takewhile(lambda x: x[-1] > 1, c.most_common()))
[(1, 5), (3, 4), (2, 3), (7, 2)]

(OP 编辑)或者,使用 列表理解 来获取计数 > 1 的项目列表 -

 [item[0] for item in counts.most_common() if item[-1] > 1]

请记住,这不如 itertools.takewhile 解决方案有效。例如,如果你有一个计数 > 1 的项目,以及一百万个计数等于 1 的项目,你最终会迭代列表一百万零一次,而你不必这样做(因为 most_common 按降序返回频率计数)。使用 takewhile 情况并非如此,因为一旦 count > 1 的条件变为假,您就会停止迭代。

原文由 cs95 发布,翻译遵循 CC BY-SA 3.0 许可协议

第一种方法:

没有循环呢?

 print(list(map(lambda x:x[0],b_data)).count('example'))

输出:

 2

第二种方法:

您可以使用简单的 dict 进行计算,而无需导入任何外部模块或使其变得如此复杂:

 b_data = [('example', 123), ('example-one', 456), ('example', 987)]

dict_1={}
for i in b_data:
    if i[0] not in dict_1:
        dict_1[i[0]]=1
    else:
        dict_1[i[0]]+=1

print(dict_1)

print(list(filter(lambda y:y!=None,(map(lambda x:(x,dict_1.get(x)) if dict_1.get(x)>1 else None,dict_1.keys())))))

输出:

 [('example', 2)]

测试用例 :

 b_data = [('example', 123), ('example-one', 456), ('example', 987),('example-one', 456),('example-one', 456),('example-two', 456),('example-two', 456),('example-two', 456),('example-two', 456)]

输出:

 [('example-two', 4), ('example-one', 3), ('example', 2)]

原文由 Aaditya Ura 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题