与默认命令结合使用时,计数器排序丢失



我正在尝试从(item_number, fruit)元组中获取一个列表,并计算每种水果在列表中出现的次数。这很容易collections.Counter.我正在使用most_common()

我遇到的问题是,当尝试同时显示与特定类型的水果相对应的item_numbers列表时,它们变得无序。

这是我的示例代码:

#!/usr/bin/env python
from collections import Counter, defaultdict
mylist = [
(1, 'peach'),
(2, 'apple'),
(3, 'orange'),
(4, 'apple'),
(5, 'banana'),
(6, 'apple'),
(7, 'orange'),
(8, 'peach'),
(9, 'apple'),
(10, 'orange'),
(11, 'plum'),
]
# FIRST, HANDLE JUST COUNTING THE ITEMS
normal_list = []
# append to a simple list
for item_number, fruit in mylist:
normal_list.append(fruit)
# prints just the name of each fruit and how many times it appears
for fruit, count in Counter(normal_list).most_common(10):
print(f'{fruit}tCount: {count}')  
# NOW TRY TO INCLUDE THE LIST IF ITEM NUMBERS ALSO
mydefaultdict = defaultdict(list)
# append to the defaultdict
for item_number, fruit in mylist:
mydefaultdict[fruit].append(item_number)
# prints each fruit, followed by count, and finally the list of IPs for each
for fruit, item_list in Counter(mydefaultdict).most_common(10):
print(f'{fruit}tCount: {len(item_list)}tList: {item_list}')

我得到了更简单版本的预期输出:

apple   Count: 4
orange  Count: 3
peach   Count: 2
banana  Count: 1
plum    Count: 1

但是,当我尝试将item_number列表添加到其中时,结果不再排序,当我使用小于水果品种总数的most_common()值时,这会造成严重破坏:

plum    Count: 1    List: [11]
banana  Count: 1    List: [5]
orange  Count: 3    List: [3, 7, 10]
apple   Count: 4    List: [2, 4, 6, 9]
peach   Count: 2    List: [1, 8]

我确信我可以在这里做一些不同的事情,但我不太确定是什么。

Counter(mydefaultdict)没有做你认为它正在做的事情。您正在向Counter提供defaultdict列表,其目的是计算出现次数,而不是计算列表的长度。实际上,Counter对象的只是列表,而不是整数。Counter不会抱怨,因为它是dict的子类,就像dict可以用另一个字典初始化一样。

要按最长列表排序,您可以将heapq.nlargest与自定义函数一起使用:

from heapq import nlargest
for fruit, item_list in nlargest(10, mydefaultdict.items(), key=lambda x: len(x[1])):
print(f'{fruit}tCount: {len(item_list)}tList: {item_list}')
apple   Count: 4    List: [2, 4, 6, 9]
orange  Count: 3    List: [3, 7, 10]
peach   Count: 2    List: [1, 8]
banana  Count: 1    List: [5]
plum    Count: 1    List: [11]

这部分很难:

Counter(mydefaultdict)

您的对象mydefaultdict已填充了列表作为值,但Counter对象通常具有正整数作为值。 这实际上不是一个错误,因为Counter是一个字典子类,所以它将接受任何字典作为初始值设定项参数。除了有一个问题:most_common不再返回理智的结果(如果你好奇,它实际上是根据列表放置词典顺序(。

也许更清楚的是这样的事情:

most_common_fruits = sorted(mydefaultdict, key=lambda f: len(mydefaultdict[f]), reverse=True)
for fruit in most_common_fruits:
item_list = mydefaultdict[fruit]
...

现在输出是这样的:

apple   Count: 4    List: [2, 4, 6, 9]
orange  Count: 3    List: [3, 7, 10]
peach   Count: 2    List: [1, 8]
banana  Count: 1    List: [5]
plum    Count: 1    List: [11]

最新更新