python如何在不从列表中删除元素的情况下按事件对列表进行排序?

python如何在不从列表中删除元素的情况下按事件对列表进行排序?,python,python-2.7,list,sorting,frequency,Python,Python 2.7,List,Sorting,Frequency,只是想知道在Python2.7中如何按频率/出现次数对列表进行排序,如果两个元素出现的次数相同,那么在原始列表中首先出现的元素将位于新列表中其他元素的前面 例如: list = [5,6,8,9,8,8,3,4,4,6,6] sorted_list = [6,6,6,8,8,8,4,4,5,9,3] 知道为什么解对[1,3,3,2,2,2,1,1]无效吗?输出是[3,3,3,2,2,2,2,1,1],但正确的输出是[1,1,1,3,3,2,2,2] 再次感谢您可以使用集合中的计数器类作为排序键

只是想知道在Python2.7中如何按频率/出现次数对列表进行排序,如果两个元素出现的次数相同,那么在原始列表中首先出现的元素将位于新列表中其他元素的前面

例如:

list = [5,6,8,9,8,8,3,4,4,6,6]
sorted_list = [6,6,6,8,8,8,4,4,5,9,3]
知道为什么解对[1,3,3,2,2,2,1,1]无效吗?输出是[3,3,3,2,2,2,2,1,1],但正确的输出是[1,1,1,3,3,2,2,2]
再次感谢

您可以使用
集合
中的
计数器
类作为排序键。由于可能有多个出现次数相同的元素,因此可以将该值本身用作辅助排序键,以便将相同的元素分组在一起:

>>> from collections import Counter
>>> lst = [5,6,8,9,8,8,3,4,4,6,6] 
>>> c = Counter(lst)
>>> sorted(lst, key = lambda x : (c[x], x), reverse = True)
[8, 8, 8, 6, 6, 6, 4, 4, 9, 5, 3]
编辑: 正如MSeifert所评论的,应该按照第一次出现的顺序而不是元素的值来打破联系。这可以使用原始列表上的
index
功能完成:

>>> sorted(lst, key = lambda x : (-1 * c[x], lst.index(x)))
[6, 6, 6, 8, 8, 8, 4, 4, 5, 9, 3]

要进行这种排序,您需要找到每个项目的第一个索引和计数。我将使用一个函数来实现这两种功能,但还有其他方法:

def count_and_first_index(it):
    dct_counts = {}
    dct_first = {}
    for idx, item in enumerate(it):
        if item in dct_counts:
            dct_counts[item] += 1
        else:
            dct_counts[item] = 1
            dct_first[item] = idx

    return dct_counts, dct_first
然后,使用
-参数进行排序很简单:

>>> lst = [5,6,8,9,8,8,3,4,4,6,6]

>>> counts, firstidx = count_and_first_index(lst)

>>> sorted(lst, key=lambda x: (counts[x], -firstidx[x]), reverse=True)
[6, 6, 6, 8, 8, 8, 4, 4, 5, 9, 3]
我否定了
索引
,因为它的排序是反向的,而您需要的是第一项。但是,您也可以取消计数,并删除反向计数:

>>> sorted(lst, key=lambda x: (-counts[x], firstidx[x]))
[6, 6, 6, 8, 8, 8, 4, 4, 5, 9, 3]

二级排序键在我心中总是有一个特殊的位置,我想你忘了定义
c
@Jean-Françoisfare-yup-我试了几次,直到我做对了,并且试着只复制粘贴相关的行。显然,我忘记了一个:-)编辑和修复,谢谢注意!然而,问题希望出现次数相同的项目以“首次出现的顺序”出现,而不是以其“价值”出现。注意预期输出中的
5,9,3
与您的
9,5,3
相比。但是,新版本是O(n²),由于对每个列表项进行了索引。我刚刚发布了一个答案,但我想知道为什么在您预期的输出中,
8
6
之前,即使
6
在原始列表中首先出现?很抱歉,我弄乱了所需的输出,我现在更改了它,感谢Seifert的(&my)代码为
[1,3,3,2,2,1,1]给出了正确的答案
,我想Mureinik的更新版本也可以,但我还没有测试过。我想你也可以做
排序(lst,key=lambda x:(-lst.count(x),lst.index(x))
,尽管它进行计数和索引(O(n^2)而不是O(n))的方式效率相当低。@PM2Ring是的,这就是我写这篇文章的原因“我将使用一个函数来完成这两项工作,但还有其他方法。”我觉得如果使用
O(n**2)
方法(它也会遍历列表两次,因为
count
index
是独立的操作!),那么
O(n)
方法是(短且)可能的。那么,2O(n²)仍然是O(n²):)@PM2Ring是的,但这并没有让我感觉更好。不过我建议你也把你的建议作为另一个答案发布。它非常简短(代码方面)简而言之,
count
index
非常快。有些人喜欢:)我想我可以发布一个单独的答案,但这主要是解释为什么你不应该这样做,除非由于O(n²)问题,列表非常小,他们应该真正使用你的解决方案。:)