2017-02-22 4 views
3

python 2.7でどのように頻度/オカレンスでリストをソートするのでしょうか?2つの要素が同じ回数発生した場合、元のリストの最初に現れる要素は、新しいリストの他の要素よりも先です。例えばpythonリストから要素を削除しないで、オカレンスごとにリストをソートするにはどうすればいいですか?

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,2,2,2] です。ありがとう

+2

私は答えを掲示していませんが期待される出力に '8'は' 6'はで最初に発生したにもかかわらず、 '6'前に、なぜ私は思ったんだけど元のリスト? – MSeifert

+0

申し訳ありませんが、私は今すぐお礼を変更しました。希望の出力を – jonny

+0

MSeifertの(&my)コードは、[[1,3,3,3,2,2,2,1,1] 'の正しい答えを返します。 Mureinikのアップデート版もありますが、私はそれをテストしていません。 –

答えて

2

Counterクラスをソートキーとしてcollectionsから取得します。あなたは同一の要素を一緒にグループ化されるように、セカンダリソートキーとしての値そのものを使用することができ、発生の同じ番号を持つ複数の要素を有することができるので:

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

EDIT:MSeifertはコメントとして 、タイは破壊されなければなりません要素の値ではなく、最初の出現の順番で表示されます。これは、元のリストにindex機能を使用して行うことができます。

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

セカンダリソートキーはいつも私の心の中に特別な場所を持っています –

+0

あなたは 'c 'を定義するのを忘れてしまったと思います。 –

+0

@ Jean-FrançoisFabreyup - 私はそれが正しいと思うまで数回試してみました。関連する行明らかに、私は1つを忘れました:-)編集し、修正、気づいていただきありがとうございます! – Mureinik

2

あなたが最初の指標と各項目のカウントを見つける必要があるソートのこの種を行うには。私は両方を行うための機能を使用しますが、他のアプローチもあります:

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 -argumentを使用して簡単です:

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

私はあなたが 'sorted(lst、key = lambda x:( - lst.count(x)、lst.index(x)))')を実行することもできたと思いますが、これはカウントとインデックス作成の仕方がかなり非効率的です(O(n)の代わりにO(n^2))。 –

+0

@ PM2Ringそう、私はこう書いています。「私は両方を行うために一つの関数を使用しますが、他の方法もあります」と書いています。 'O(n)'アプローチを使用すると、( 'count'と' index'は別々の操作であるため、リストを2回横断します)、私は 'O(n ** 2)短いと)可能です。 – MSeifert

+0

さて、2O(n²)はまだO(n²)です。 –

関連する問題