我试图使用Python的Counter from collection模块在列表中排序一些值。但它给出了奇怪的结果
>>> diff=["aaa","aa","a"]
>>> c=Counter(diff)
>>> sorted(c.items(), key = lambda x:x[1] , reverse=True)
[('aa', 1), ('a', 1), ('aaa', 1)]
>>> c.items()
[('aa', 1), ('a', 1), ('aaa', 1)]
输出很奇怪,因为它似乎将'aa'洗牌到第一位,然后是'a'和'aaa'。理想情况下,它应该是'a'然后'aa'然后'aaa'
这背后的原因是什么,你将如何纠正这一点
编辑:大多数人都不正确地理解这个问题,因此我正在推动一些澄清。目标是根据列表的出现对列表中的单词数进行排序。
让我们说列出diff = ["this", "this", "world", "cool", "is", "cool", "cool"]
。我上面的代码的最终输出将是cool
然后this
然后is
然后world
这是正确的。
但问题是当你提供相同的出现相同的字符,python行为不端。由于输入是diff = ["aaa", "aa", "a"]
,我预计输出为a
然后aa
然后aaa
。但是python算法永远不会知道每个单词都是单次出现的。
但如果是这样,那么为什么python没有打印aaa
然后aa
然后a
(即输入的顺序相同)给予怀疑。 Python排序确实交换了。为什么?
Counter
是dict
的子类。这是一个无序的集合。
得到你想要的排序顺序,你可以更新你的代码 -
sorted(c.items(), key = lambda x:(x[1], -len(x[0])) , reverse=True)
这给了 -
[('a', 1), ('aa', 1), ('aaa', 1)]
sorted
做了stable sort。这意味着对于关系,项目的顺序将与它们在原始输入中出现的顺序相同。由于你的Counter
是无序的,所以sorted
的输入是一些未定义的顺序。如果你想要你可以按键排序,然后是值:
sorted(sorted(c.items(), key=lambda x:x[0], reverse=True), key = lambda x:x[1] , reverse=True)
或者(可能更好)让你的sort函数返回一个元组作为排序键:
sorted(c.items(), key=lambda x:(x[1], x[0]), reverse=True)
使用operator.itemgetter
的(甚至更好!)版本:
sorted(c.items(), key=itemgetter(1,0), reverse=True)
这是确保订单保持不变的一种方法。
如前所述,字典不被视为订购。结果将是元组的排序列表。
from collections import Counter
diff = ["aaa", "aa", "a"]
c = Counter(diff)
sorted(c.items(), key=lambda x: diff.index(x[0]))
# [('aaa', 1), ('aa', 1), ('a', 1)]