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

python How do you sort list by occurrence with out removing elements from the list?

只是想知道如何在 python 2.7 中按 frequency/occurrence 对列表进行排序,如果 2 个元素出现的次数相同,则在原始列表中首先出现的元素排在前面新列表中的另一个元素。

例如:

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,3,2,2,2,1,1]。输出是 [3,3,3,2,2,2 ,1,1,1] 但正确的输出是 [1,1,1,3,3,3,2,2,2] 再次感谢

您可以使用 collections 中的 Counter class 作为排序键。由于您可能有多个出现次数相同的元素,您可以使用值本身作为辅助排序键,以便将相同的元素组合在一起:

>>> 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

然后使用 key 参数进行排序很简单:

>>> 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]

我否定了 index 因为它的排序是相反的,而你想要第一个项目在前。但是,您也可以否定 counts 并删除 reverse:

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