降順 - ディクショナリ python sort




辞書を値でソートするにはどうすればよいですか? (20)

Python 3.6では、組み込みのdictが注文されます

良いニュースですので、独自の文字列IDを持つデータベースから取り出されたペアをキーとして、また数値としての値を組み込みのPython v3.6 + dictにマッピングするOPのオリジナルの使用例は、挿入順序を遵守する必要があります。

たとえば、次のようなデータベースクエリの2つのカラムテーブル式が得られるとします。

SELECT a_key, a_value FROM a_table ORDER BY a_value;

2つのPythonタプルk_seqとv_seq(数値インデックスで整列され、同じ長さのもの)に格納されます:

k_seq = ('foo', 'bar', 'baz')
v_seq = (0, 1, 42)
ordered_map = dict(zip(k_seq, v_seq))

後で出力できるようにする:

for k, v in ordered_map.items():
    print(k, v)

このケースでは(新しいPython 3.6+組み込みdictのために)収穫します:

foo 0
bar 1
baz 42

vの値ごとに同じ順序で。

私のマシンにPython 3.5をインストールすると、現在のところ以下のような結果が得られます。

bar 1
foo 0
baz 42

詳細:

Raymond Hettingerによって提案されたように(2012年に提案されたpython-devのメール、より速い反復でよりコンパクトな辞書で )、今は(2016年に)Victor Stinnerの題名で"Python 3.6 dictと python- Python 3.6で「コンパクトで順序付けられたdict」という問題27350の修正/実装により、組み込みのdictを使用して挿入順序を維持できるようになりました。

うまくいけば、これは最初のステップとして、薄い層のOrderedDict実装につながります。 @ JimFasarakis-Hilliardが示しているように、OrderedDict型のユースケースも将来見ることができます。 私は大規模なPythonコミュニティが、これが時間のテストに耐えられるかどうか、そして次のステップがどんなものになるかを慎重に調べると思います。

安定した発注によって開かれた可能性を見逃さないように、コーディングの習慣を再考する時間:

  • キーワード引数
  • (中間)記憶装置

関数とメソッドの実装では、ディスパッチを容易にするため、最初の方法があります。

第2は、パイプラインの処理における中間記憶としての使用をより容易にすることを奨励するからです。

Raymond Hettinger氏はサンフランシスコのPython Meetup Groupプレゼンテーション2016-DEC-08の「 The Tech Behind Python 3.6 Dictionaries 」を説明するドキュメントを親切に提供しました。

そして多分かなりのStack Overflow質問と回答ページにはこの情報の変形があり、多くの高品質の回答にはバージョンごとの更新が必要になります。

Caveat Emptor(ただし、下記のupdate 2017-12-15を参照):

@ajcrは正当な点として、「この新しいインプリメンテーションの注文を保存する面はインプリメンテーションの詳細とみなされ、依拠するべきではありません」と述べています。 ( whatsnew36から)nit pickingではなく 、引用は少し悲観的にカットされました;-)。 これは将来も変わるかもしれませんが、現在および将来のすべてのPython実装での順序保持セマンティクスを強制するために言語仕様を変更する前に、いくつかのリリースの言語でこの新しいdict実装を使用することが望まれます。ランダムな繰り返し命令がまだ有効な古いバージョンの言語(例えば、Python 3.5)との下位互換性を維持するのに役立ちます。

いくつかの人間の言語(ドイツ語など)のように、使用法によって言語が形作られ、現在はwhatsnew36で宣言されています。

アップデート2017-12-15:

python-devリストへのメールで 、Guido van Rossumは次のように宣言しました。

それをそうする。 「Dictは挿入注文を維持する」という判決です。 ありがとう!

したがって、dict挿入順序のバージョン3.6 CPythonの副作用は、言語仕様の一部になりつつあります(実装の詳細だけではありません)。 このメールスレッドは、議論の中でRaymond Hettingerが思い出したように、 collections.OrderedDictためのいくつかの顕著なデザイン目標を浮き彫りにしていました。

私はデータベースの2つのフィールドから読み込まれた値の辞書を持っています:文字列フィールドと数値フィールド。 文字列フィールドはユニークなので、辞書のキーです。

私はキーを並べ替えることができますが、値に基づいてどのようにソートできますか?

注:私はStack Overflowの質問を読んでいます。 辞書のリストをPythonの辞書の値で並べ替えるにはどうすればよいですか? おそらく辞書のリストを持つように私のコードを変更することができますが、実際には辞書のリストは必要ないので、もっと簡単な解決法があるかどうかを知りたいと思っていました。


同じように単純に: sorted(dict1, key=dict1.get)

まあ、実際には、 "辞書値によるソート"を行うことは可能です。 最近、私はコードゴルフ(スタックオーバーフロー質問コードゴルフ:単語の頻度チャート )でそれをしなければならなかった。 要約すると、問題は種類があり、テキストが与えられたとき、各単語がどれほど頻繁に遭遇するかをカウントし、頻度の低い順にソートされたトップワードのリストを表示する。

単語をキーとして、各単語の出現回数を値として辞書を構築すると、ここでは簡略化されます。

from collections import defaultdict
d = defaultdict(int)
for w in text.split():
  d[w] += 1

sorted(d, key=d.get)を使用頻度でsorted(d, key=d.get)られた単語のリストを取得できます。ソートキーとして単語の出現回数を使用して、ソートは辞書キーを繰り返します。

for w in sorted(d, key=d.get, reverse=True):
  print w, d[w]

私はこの詳細な説明を書いて、「キーで辞書を簡単にソートすることはできますが、値でソートするにはどうすればよいですか」ということをよく説明しています - そして、OPはそのような問題に対処しようとしていたと思います。 そして、解決策は、上記のように、値に基づいてキーの並べ替えを行うことです。


Python 2.7では、次のようにします。

from collections import OrderedDict
# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by key
OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

コピー貼り付け: http://docs.python.org/dev/library/collections.html#ordereddict-examples-and-recipes : http://docs.python.org/dev/library/collections.html#ordereddict-examples-and-recipes

楽しい ;-)


dictを繰り返し、値を降順で並べ替えます。

$ python --version
Python 3.2.2

$ cat sort_dict_by_val_desc.py 
dictionary = dict(siis = 1, sana = 2, joka = 3, tuli = 4, aina = 5)
for word in sorted(dictionary, key=dictionary.get, reverse=True):
  print(word, dictionary[word])

$ python sort_dict_by_val_desc.py 
aina 5
tuli 4
joka 3
sana 2
siis 1

collections.Counterを使用することができます。 これは、数値と非数値の両方の値に対して機能することに注意してください。

>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> from collections import Counter
>>> #To sort in reverse order
>>> Counter(x).most_common()
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> Counter(x).most_common()[::-1]
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
>>> #To get a dictionary sorted by values
>>> from collections import OrderedDict
>>> OrderedDict(Counter(x).most_common()[::-1])
OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])

dicts ValueSortedDictを使用しdicts

from dicts.sorteddict import ValueSortedDict
d = {1: 2, 3: 4, 4:3, 2:1, 0:0}
sorted_dict = ValueSortedDict(d)
print sorted_dict.items() 

[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]

更新:Python 3.5を使用して2015年12月5日

受け入れられた答えが有用であることが判明したOrderedDict 、このタイプの問題を正確に解決するために設計された、現実的で現代的な代替案として、標準ライブラリコレクションモジュールからOrderedDictを参照するOrderedDict更新されていないことにも驚きました。

from operator import itemgetter
from collections import OrderedDict

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = OrderedDict(sorted(x.items(), key=itemgetter(1)))
# OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])

公式なOrderedDictドキュメントも非常によく似た例ですが、ソート関数にラムダを使用しています:

# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
# OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

Dilettantによって指摘されているように 、Python 3.6は今すぐ注文を保持します ! 私は、iterable(tuple、list、dict)のソートを楽にする関数を共有すると思いました。 後者の場合、キーまたは値のいずれかをソートすることができ、数値比較を考慮に入れることができます。 > = 3.6の場合のみ!

たとえば、文字列とintを保持するiterableでsortedを使用しようとすると、sorted()は失敗します。 もちろん、str()との文字列比較を強制することもできます。 ただし、 実際の数値比較を行う場合は、 1220より小さい場合(文字列比較ではそうではありません)。 だから私は次のことを思いついた。 明示的な数値比較が必要なときは、すべての値を浮動小数点数に変換しようとすることによって明示的な数値ソートを試みるフラグnum_as_numを使用することができます。 成功した場合は数値ソートを行い、そうでない場合は文字列比較を行います。

改善やプッシュリクエストのコメントは大歓迎です。

def sort_iterable(iterable, sort_on=None, reverse=False, num_as_num=False):
    def _sort(i):
      # sort by 0 = keys, 1 values, None for lists and tuples
      try:
        if num_as_num:
          if i is None:
            _sorted = sorted(iterable, key=lambda v: float(v), reverse=reverse)
          else:
            _sorted = dict(sorted(iterable.items(), key=lambda v: float(v[i]), reverse=reverse))
        else:
          raise TypeError
      except (TypeError, ValueError):
        if i is None:
          _sorted = sorted(iterable, key=lambda v: str(v), reverse=reverse)
        else:
          _sorted = dict(sorted(iterable.items(), key=lambda v: str(v[i]), reverse=reverse))

      return _sorted

    if isinstance(iterable, list):
      sorted_list = _sort(None)
      return sorted_list
    elif isinstance(iterable, tuple):
      sorted_list = tuple(_sort(None))
      return sorted_list
    elif isinstance(iterable, dict):
      if sort_on == 'keys':
        sorted_dict = _sort(0)
        return sorted_dict
      elif sort_on == 'values':
        sorted_dict = _sort(1)
        return sorted_dict
      elif sort_on is not None:
        raise ValueError(f"Unexpected value {sort_on} for sort_on. When sorting a dict, use key or values")
    else:
      raise TypeError(f"Unexpected type {type(iterable)} for iterable. Expected a list, tuple, or dict")


あなたは値で永久にソートされている辞書であるスキップ辞書を使うことができます。

>>> data = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
>>> SkipDict(data)
{0: 0.0, 2: 1.0, 1: 2.0, 4: 3.0, 3: 4.0}

keys()values()またはitems()を使用すると、ソートされた順序で値ごとに反復処理されます。

スキップリストのデータ構造を使用して実装されています。


これは、値が高い順にソートされた辞書のキーと値のペアのリストを返します。

sorted(d.items(), key=lambda x: x[1], reverse=True)

キーでソートされた辞書の場合は、次のようにします。

sorted(d.items(), reverse=True)

辞書自体はソートできないため、戻り値はタプルのリストです。

これは、印刷されるか、またはさらなる計算に送られる。


これはコードです:

import operator
origin_list = [
    {"name": "foo", "rank": 0, "rofl": 20000},
    {"name": "Silly", "rank": 15, "rofl": 1000},
    {"name": "Baa", "rank": 300, "rofl": 20},
    {"name": "Zoo", "rank": 10, "rofl": 200},
    {"name": "Penguin", "rank": -1, "rofl": 10000}
]
print ">> Original >>"
for foo in origin_list:
    print foo

print "\n>> Rofl sort >>"
for foo in sorted(origin_list, key=operator.itemgetter("rofl")):
    print foo

print "\n>> Rank sort >>"
for foo in sorted(origin_list, key=operator.itemgetter("rank")):
    print foo

結果は次のとおりです。

元の

{'name': 'foo', 'rank': 0, 'rofl': 20000}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Baa', 'rank': 300, 'rofl': 20}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Penguin', 'rank': -1, 'rofl': 10000}

ロルフ

{'name': 'Baa', 'rank': 300, 'rofl': 20}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Penguin', 'rank': -1, 'rofl': 10000}
{'name': 'foo', 'rank': 0, 'rofl': 20000}

ランク

{'name': 'Penguin', 'rank': -1, 'rofl': 10000}
{'name': 'foo', 'rank': 0, 'rofl': 20000}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Baa', 'rank': 300, 'rofl': 20}

キーに渡すことができるカスタム関数を使用することもできます。

def dict_val(x):
    return x[1]
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=dict_val)

もう一つの方法はlabmda関数を使うことです

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=lambda t: t[1])

ハンク・ゲイの答えとほとんど同じです。

    sorted([(value,key) for (key,value) in mydict.items()])

または、John Fouhyの提案どおりに最適化してください。

    sorted((value,key) for (key,value) in mydict.items())


値が数値の場合は、コレクションからカウンタを使用することもできます

from collections import Counter

x={'hello':1,'python':5, 'world':3}
c=Counter(x)
print c.most_common()


>> [('python', 5), ('world', 3), ('hello', 1)]    

値が整数で、Python 2.7以降を使用する場合は、 dict代わりにcollections.Counterを使用できます。 most_commonメソッドは、値でソートされたすべてのアイテムを表示します。


最近のPython 2.7には、アイテムが追加された順序を記憶する新しいOrderedDictタイプがあります。

>>> d = {"third": 3, "first": 1, "fourth": 4, "second": 2}

>>> for k, v in d.items():
...     print "%s: %s" % (k, v)
...
second: 2
fourth: 4
third: 3
first: 1

>>> d
{'second': 2, 'fourth': 4, 'third': 3, 'first': 1}

元の新しい順序付き辞書を作成し、値でソートするには:

>>> from collections import OrderedDict
>>> d_sorted_by_value = OrderedDict(sorted(d.items(), key=lambda x: x[1]))

OrderedDictは通常のdictのように動作します。

>>> for k, v in d_sorted_by_value.items():
...     print "%s: %s" % (k, v)
...
first: 1
second: 2
third: 3
fourth: 4

>>> d_sorted_by_value
OrderedDict([('first': 1), ('second': 2), ('third': 3), ('fourth': 4)])

次の方法を試してみてください。 以下のデータを持つmydictという辞書を定義しましょう:

mydict = {'carl':40,
          'alan':2,
          'bob':1,
          'danny':3}

辞書でキーをソートする場合は、次のようなことができます。

for key in sorted(mydict.iterkeys()):
    print "%s: %s" % (key, mydict[key])

これにより、次の出力が返されます。

alan: 2
bob: 1
carl: 40
danny: 3

一方、質問で質問されるように、値で辞書を並べ替えることを望むなら、次のことができます:

for key, value in sorted(mydict.iteritems(), key=lambda (k,v): (v,k)):
    print "%s: %s" % (key, value)

このコマンドの結果(辞書を値でソート)は、次の値を返します。

bob: 1
alan: 2
danny: 3
carl: 40

私は同じ問題を抱えていました。私はこれを次のように解決しました。

WantedOutput = sorted(MyDict, key=lambda x : MyDict[x]) 

「私はキーを並べ替えることができますが、値に基づいてどのように並べ替えることができますか」というのは明らかに、キーは値の値に従ってソートされます)。

注文がうまく定義されていないことに注意してください(同じ値を持つキーは出力リストの任意の順序になります)。


辞書をソートすることはできません。ソートされた辞書の表現を取得するためだけです。 辞書は本質的に無秩序ですが、リストやタプルなどの他のタイプはそうではありません。 したがって、ソートされた値を表すために順序付けされたデータ型が必要です。リストはおそらくタプルのリストになります。

例えば、

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(1))

sorted_xは各タプルの2番目の要素でソートされたタプルのリストになります。 dict(sorted_x) == x

また、値の代わりにキーをソートする場合は、次のようにします。

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(0))

Python3ではアンパックが許可されていないので[1]

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_by_value = sorted(x.items(), key=lambda kv: kv[1])






dictionary