pythonは回数ソートを実現し、出現順序を維持する


問題の背景:
リストデータがあり、出現回数が最も多いものに従って周波数を下げてソートし、回数が同じ場合、データの出場順序を維持します.
C++を使用する場合は優先キューと辞書カウントが必要ですが、pythonはそんなに複雑ではないでしょう.
#    :
data = [7, 3, 3, 3, 5, 5, 5, 5, 6, 6, 6, 1]

#    :
ans = [5, 5, 5, 5, 3, 3, 3, 6, 6, 6, 7, 1]

ソリューション1:
辞書を使用してカウントし、辞書のvalueをソートし、最後にターゲット配列に結合します.
"""
        ,      defaultdict   :
dic = {1: [1, 11], 3: [3, 1], 5: [4, 4], 6: [3, 8], 7: [1, 0]}
   dic  sorted()        ,  key           ,      
           
"""
data = [7,3,3,3,5,5,5,5,6,6,6,1]

def times_sort(data:list):
    from collections import defaultdict
    times = defaultdict(list)

    for i in data:
        if i not in times:
            times[i].append(data.count(i))
            times[i].append(data.index(i))

    dic = sorted(times.items(), key=lambda item: (-item[1][0], item[1][1]))

    res = []
    for (k, v) in dic:
        #print(k,v)
        res += [k]*v[0]

    return res

print(times_sort(data))

ソリューション2:
辞書を使う必要はなく、pythonのsetを直接使って重さを取り除き、(key,times,index)をメタグループとしてsorted関数に直接送り込んで高度な比較を行うことができます.
"""
     ,     (key, times, index)            
input:[(1, 1, 11), (3, 3, 1), (5, 4, 4), (6, 3, 8), (7, 1, 0)]
ouput: [(5, 4, 4), (3, 3, 1), (6, 3, 8), (7, 1, 0), (1, 1, 11)]
"""
def times_sort(data:list):
    value = set(data)
    times = []
    index = []

    for i in value:
        times.append(data.count(i))
        index.append(data.index(i))

    res = []
    for i in zip(value, times, index):
        res.append(i)
    res = sorted(res, key=lambda x:(-x[1],x[2]))  #        ,         

    ans = []
    for item in res:
        ans += [item[0]]*item[1]

    return ans

print(times_sort(data))

 
reference:
Python統計リスト(List)における重複項目の出現回数を並べ替え
pythonソートsorted最初の条件が同じ場合は2番目の条件でソート
強制格を上げる2つの関数:setdefaultとdefaultdict