辞書をキーでソートするにはどうすればよいですか?


940

行くには良い方法は何でしょう{2:3, 1:89, 4:5, 3:0}{1:89, 2:3, 3:0, 4:5}
私はいくつかの投稿をチェックしましたが、それらはすべてタプルを返す「ソートされた」演算子を使用しています。


39
辞書は本質的にソートされていません。辞書の表示は別の問題です。とにかく、あなたはそれを本当に分類する必要がありますか?
Karl Knechtel、2012年

15
辞書はソートされていません。彼らはただ逃げる。要素を調べたい場合は、dを辞書の名前と仮定して、「for key in sorted(d.keys())」のようにソートを使用して言ったようなことを行う必要があります
Ryan Haining

3
@KarlKnechtel-私のユースケースは、プリミティブメニューを持つCLIアプリケーションがあり、メニューオプションがキーとして辞書にあることです。ユーザーの健全性のためにキーをアルファベット順に表示したいと思います。
Randy


4
辞書は挿入順で並べられていることに注意してください(python 3.6+)。以下のいくつかの回答はこれを指摘しています。
matiasg

回答:


940

標準のPython辞書は順不同です。(キー、値)のペアを並べ替えたとしてもdict、順序を維持するような方法でそれらを格納することはできません。

最も簡単な方法はを使用OrderedDictすることです。これにより、要素が挿入された順序が記憶されます。

In [1]: import collections

In [2]: d = {2:3, 1:89, 4:5, 3:0}

In [3]: od = collections.OrderedDict(sorted(d.items()))

In [4]: od
Out[4]: OrderedDict([(1, 89), (2, 3), (3, 0), (4, 5)])

od印刷方法は気にしないでください。期待どおりに動作します:

In [11]: od[1]
Out[11]: 89

In [12]: od[3]
Out[12]: 0

In [13]: for k, v in od.iteritems(): print k, v
   ....: 
1 89
2 3
3 0
4 5

Python 3

Python 3ユーザーの場合、の.items()代わりにを使用する必要があります.iteritems()

In [13]: for k, v in od.items(): print(k, v)
   ....: 
1 89
2 3
3 0
4 5

1
私はこれを使用しましたが、機能します。より多くのコードと冗長性があると思いますが、仕事は完了しています。#unordered dict d = {2:3、1:89、4:5、3:0} orderedDict = {}ソートされたキー(d.iterkeys()):orderedDict [key] = d [key]
アントニー

4
@achrysochoou:うまくいったなら、それは運が良かったに違いない。ご存じのように、通常の辞書には、ソートされたキーを割り当てても、ランダムに割り当てても、ソートの概念はありません。
RicardoCárdenes2012年

21
python 3.7以降の場合:sorted_dict = dict(sorted(unsorted_dict.items()))
aksh1618

10
Python 3.7以降では、orderedDictは必要ありません。デフォルトで注文できるようになりました:-)
Aneuway '25年

3
Python 3.7.4マニュアルから:「ディクショナリでlist(d)を実行すると、ディクショナリで使用されているすべてのキーのリストが挿入順に返されます。したがって、挿入順序は保持され、信頼できるものです。
モスタファハディアン

415

辞書自体には注文されたアイテムはありません。それらを印刷したい場合など、いくつかの例を以下に示します。

Python 2.4以降:

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

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

与える:

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

(2.4以下のPython :)

keylist = mydict.keys()
keylist.sort()
for key in keylist:
    print "%s: %s" % (key, mydict[key])

出典:http : //www.saltycrane.com/blog/2007/09/how-to-sort-python-dictionary-by-keys/


2
NPEの回答のようにPython 2.4以降でOrderedDictを使用することもできます
radtek

1
また、items()を使用している場合は、次のようにできますfor key, value in sorted(mydict.items())"
beep_check

辞書自体には、注文されたアイテムはありません ->もう当てはまりません!
minexew

どうして説明できますか
ジェームズ

204

Pythonのcollectionsライブラリのドキュメント

>>> from collections import OrderedDict

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

>>> # dictionary sorted by key -- OrderedDict(sorted(d.items()) also works
>>> 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)])

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

4
驚くばかり!みんなあなたが順序(降順昇順TO)を逆にしたいならば、あなたは、単に追加reverse=TrueなどをOrderedDict(sorted(d.items(), reverse=True, key=lambda t: t[0]))
benscabbia

1
PyCharmでは、私が使う辞書を何に関係なく、私はいつもこの警告を得る:Unexpected type(s): (List[str]) Possible types: (Mapping) (Iterable[Tuple[Any, Any]])
Euler_Salter

153

CPython / PyPy 3.6、およびPython 3.7以降の場合、これは次のようにして簡単に実行できます。

>>> d = {2:3, 1:89, 4:5, 3:0}
>>> dict(sorted(d.items()))
{1: 89, 2: 3, 3: 0, 4: 5}

3
同じことを書く別の方法は、内包表記を使用することです {key:d[key] for key in sorted(d.keys())}
。– flow2k

41

ソートされた順序でキーを自動的に維持するディクショナリ実装を提供する多くのPythonモジュールがあります。pure-Pythonおよびfast-as-C実装であるsortedcontainersモジュールを検討してください。互いにベンチマークされた他の一般的なオプションとのパフォーマンス比較もあります。

順序付けされたdictを使用することは、繰り返しながらキーと値のペアを常に追加および削除する必要がある場合には不十分なソリューションです。

>>> from sortedcontainers import SortedDict
>>> d = {2:3, 1:89, 4:5, 3:0}
>>> s = SortedDict(d)
>>> s.items()
[(1, 89), (2, 3), (3, 0), (4, 5)]

SortedDict型は、組み込みのdict型では不可能なインデックス付きの場所の検索と削除もサポートします。

>>> s.iloc[-1]
4
>>> del s.iloc[2]
>>> s.keys()
SortedSet([1, 2, 4])

32

単に:

d = {2:3, 1:89, 4:5, 3:0}
sd = sorted(d.items())

for k,v in sd:
    print k, v

出力:

1 89
2 3
3 0
4 5

6
sd辞書ではなく、タプルのリストです。(まだ便利です。)
nischi

24

他の人が述べたように、辞書は本質的に順不同です。ただし、問題が辞書を順番に表示するだけの場合は__str__、辞書サブクラスでメソッドをオーバーライドして、組み込みではなくこの辞書クラスを使用できますdict。例えば。

class SortedDisplayDict(dict):
   def __str__(self):
       return "{" + ", ".join("%r: %r" % (key, self[key]) for key in sorted(self)) + "}"


>>> d = SortedDisplayDict({2:3, 1:89, 4:5, 3:0})
>>> d
{1: 89, 2: 3, 3: 0, 4: 5}

これは、キーの保存方法、キーを反復したときにキーが戻る順序など、何も変更しないことに注意してくださいprint。Pythonコンソールで、またはpythonコンソールでどのように表示されるかだけです。


19

別の方法を見つけました:

import json
print json.dumps(d, sort_keys = True)

upd:
1.これはネストされたオブジェクトもソートします(@DanielFに感謝します)。
2. python辞書は順序付けされていないため、印刷またはstrへの割り当てにのみ使用できます。


しかし、これはネストされたオブジェクトのキーもソートするため、不要な場合があります。
ダニエルF

これは辞書ではなくリストのみをソートすることに注意してください。たとえば、dict.keys()はリストであるためソートされません。
Andrew


13

Python 3.6以前は、Python辞書は順不同でした。Python 3.6のCPython実装では、辞書は挿入順序を保持します。Python 3.7以降、これは言語機能になります。

Python 3.6の変更履歴(https://docs.python.org/3.6/whatsnew/3.6.html#whatsnew36-compactdict):

この新しい実装の順序を維持する側面は、実装の詳細と見なされ、信頼すべきではありません(これは将来変更される可能性がありますが、言語仕様を変更する前に、この新しいdict実装をいくつかのリリースで使用することが望ましいです)現在および将来のすべてのPython実装に順序を維持するセマンティクスを義務付けるために、これは、ランダムな反復順序がまだ有効である古いバージョンの言語(Python 3.5など)との下位互換性を維持するのにも役立ちます。

Python 3.7のドキュメント(https://docs.python.org/3.7/tutorial/datastructures.html#dictionaries):

辞書に対してlist(d)を実行すると、辞書で使用されているすべてのキーのリストが挿入順に返されます(並べ替えたい場合は、代わりにsorted(d)を使用してください)。

したがって、以前のバージョンとは異なり、Python 3.6 / 3.7の後に辞書を並べ替えることができます。内部のサブ辞書を含むネストされた辞書をソートしたい場合は、次のようにすることができます:

test_dict = {'a': 1, 'c': 3, 'b': {'b2': 2, 'b1': 1}}

def dict_reorder(item):
    return {k: sort_dict(v) if isinstance(v, dict) else v for k, v in sorted(item.items())}

reordered_dict = dict_reorder(test_dict)

https://gist.github.com/ligyxy/f60f0374defc383aa098d44cfbd318eb


11

ここで、Python dictをキーを使用して並べ替える最も簡単な解決策を見つけましたpprint。例えば。

>>> x = {'a': 10, 'cd': 20, 'b': 30, 'az': 99} 
>>> print x
{'a': 10, 'b': 30, 'az': 99, 'cd': 20}

しかしpprintを使用している間はソートされたdictを返します

>>> import pprint 
>>> pprint.pprint(x)
{'a': 10, 'az': 99, 'b': 30, 'cd': 20}

10

辞書を並べ替える簡単な方法があります。

あなたの質問によると、

解決策は次のとおりです。

c={2:3, 1:89, 4:5, 3:0}
y=sorted(c.items())
print y

(ここで、cは辞書の名前です。)

このプログラムは、次の出力を提供します。

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

あなたが欲しかったように。

別の例は次のとおりです。

d={"John":36,"Lucy":24,"Albert":32,"Peter":18,"Bill":41}
x=sorted(d.keys())
print x

出力を提供します:['Albert', 'Bill', 'John', 'Lucy', 'Peter']

y=sorted(d.values())
print y

出力を提供します:[18, 24, 32, 36, 41]

z=sorted(d.items())
print z

出力を提供します:

[('Albert', 32), ('Bill', 41), ('John', 36), ('Lucy', 24), ('Peter', 18)]

したがって、それをキー、値、アイテムに変更することで、あなたが望むもののように印刷することができます。


8

あなたが望むものを正確に生成します:

 D1 = {2:3, 1:89, 4:5, 3:0}

 sort_dic = {}

 for i in sorted(D1):
     sort_dic.update({i:D1[i]})
 print sort_dic


{1: 89, 2: 3, 3: 0, 4: 5}

しかし、これはこれを行う正しい方法ではありません。なぜなら、私が最近学んだ、さまざまな辞書で異なる動作を示す可能性があるからです。したがって、私がここで共有している私のクエリの応答で、完璧な方法がTimによって提案されました。

from collections import OrderedDict
sorted_dict = OrderedDict(sorted(D1.items(), key=lambda t: t[0]))

「異なる辞書で異なる動作を示す」とはどういう意味ですか?並べ替えが処理できない「明確な動作」とは何ですか?
ingyhere

6

最も簡単なのは、辞書をキーで並べ替え、並べ替えたキーと値のペアを新しい辞書に保存することです。

dict1 = {'renault': 3, 'ford':4, 'volvo': 1, 'toyota': 2} 
dict2 = {}                  # create an empty dict to store the sorted values
for key in sorted(dict1.keys()):
    if not key in dict2:    # Depending on the goal, this line may not be neccessary
        dict2[key] = dict1[key]

より明確にするために:

dict1 = {'renault': 3, 'ford':4, 'volvo': 1, 'toyota': 2} 
dict2 = {}                  # create an empty dict to store the sorted     values
for key in sorted(dict1.keys()):
    if not key in dict2:    # Depending on the goal, this line may not be  neccessary
        value = dict1[key]
        dict2[key] = value

6

質問に従って、現在の辞書をキーでソートすることにより、新しい辞書を作成できます。

これはあなたの辞書です

d = {2:3, 1:89, 4:5, 3:0}

ラムダ関数を使用してこのdをソートすることにより、新しい辞書d1を作成します

d1 = dict(sorted(d.items(), key = lambda x:x[0]))

d1は{1:89、2、3、3、0、4:5}で、dのキーに基づいてソートされている必要があります。


5

Python dictは順不同です。最も一般的な使用例はルックアップを行うことなので、通常、これは問題にはなりません。

必要なことを行う最も簡単な方法はcollections.OrderedDict、ソートされた順序で要素を挿入することです。

ordered_dict = collections.OrderedDict([(k, d[k]) for k in sorted(d.keys())])

反復が必要な場合は、上記の他の人が示唆しているように、ソートされたキーを反復するのが最も簡単な方法です。例-

キーでソートされた値を出力します。

# create the dict
d = {k1:v1, k2:v2,...}
# iterate by keys in sorted order
for k in sorted(d.keys()):
    value = d[k]
    # do something with k, value like print
    print k, value

キーでソートされた値のリストを取得します。

values = [d[k] for k in sorted(d.keys())]

2
for k,value in sorted(d.items()):優れている:ことを回避するにはループで再びキーで辞書にアクセスする
ジャン=フランソワ・ファーブル

4

私は単一行のdictソートを思いつきました。

>> a = {2:3, 1:89, 4:5, 3:0}
>> c = {i:a[i] for i in sorted(a.keys())}
>> print(c)
{1: 89, 2: 3, 3: 0, 4: 5}
[Finished in 0.4s]

これがお役に立てば幸いです。


4

この関数は、辞書をキーで再帰的にソートします。つまり、ディクショナリのいずれかの値がディクショナリでもある場合、その値もそのキーでソートされます。CPython 3.6以降で実行している場合は、dictではなくを使用するように変更するだけOrderedDictです。

from collections import OrderedDict

def sort_dict(d):
    items = [[k, v] for k, v in sorted(d.items(), key=lambda x: x[0])]
    for item in items:
        if isinstance(item[1], dict):
            item[1] = sort_dict(item[1])
    return OrderedDict(items)
    #return dict(items)

2

あなたは物事を複雑にしています...それは本当に簡単です

from pprint import pprint
Dict={'B':1,'A':2,'C':3}
pprint(Dict)

出力は次のとおりです。

{'A':2,'B':1,'C':3}

pprintソート辞書を表示することを知らなかったので賛成ですが、OPはソートされていない辞書からソートされた辞書への「移行」について本当に質問しました。
レプトン船長

pprintは何も返さないため、このメソッドは連鎖割り当てを許可しません。>>> adict = {'B':1、 'A':2、 'C':3} >>> ppdict = pprint(adict){'A':2、 'B':1、 'C': 3} >>> ppdict.type()トレースバック(最後の最新の呼び出し):<モジュール>のファイル "<stdin>"、1行目AttributeError: 'NoneType' object has no attribute 'type'

2

最も簡単な解決策は、dictキーのリストをソートされた順序で取得し、dictに対して反復することです。例えば

a1 = {'a':1, 'b':13, 'd':4, 'c':2, 'e':30}
a1_sorted_keys = sorted(a1, key=a1.get, reverse=True)
for r in a1_sorted_keys:
    print r, a1[r]

以下は出力です(降順)

e 30
b 13
d 4
c 2
a 1

2

これを行う簡単な方法:

d = {2:3, 1:89, 4:5, 3:0}

s = {k : d[k] for k in sorted(d)}

s
Out[1]: {1: 89, 2: 3, 3: 0, 4: 5} 

1

2.7の2つの方法のタイミング比較は、それらが実質的に同一であることを示しています。

>>> setup_string = "a = sorted(dict({2:3, 1:89, 4:5, 3:0}).items())"
>>> timeit.timeit(stmt="[(k, val) for k, val in a]", setup=setup_string, number=10000)
0.003599141953657181

>>> setup_string = "from collections import OrderedDict\n"
>>> setup_string += "a = OrderedDict({1:89, 2:3, 3:0, 4:5})\n"
>>> setup_string += "b = a.items()"
>>> timeit.timeit(stmt="[(k, val) for k, val in b]", setup=setup_string, number=10000)
0.003581275490432745 

1
from operator import itemgetter
# if you would like to play with multiple dictionaries then here you go:
# Three dictionaries that are composed of first name and last name.
user = [
    {'fname': 'Mo', 'lname': 'Mahjoub'},
    {'fname': 'Abdo', 'lname': 'Al-hebashi'},
    {'fname': 'Ali', 'lname': 'Muhammad'}
]
#  This loop will sort by the first and the last names.
# notice that in a dictionary order doesn't matter. So it could put the first name first or the last name first. 
for k in sorted (user, key=itemgetter ('fname', 'lname')):
    print (k)

# This one will sort by the first name only.
for x in sorted (user, key=itemgetter ('fname')):
    print (x)

1
dictionary = {1:[2],2:[],5:[4,5],4:[5],3:[1]}

temp=sorted(dictionary)
sorted_dict = dict([(k,dictionary[k]) for i,k in enumerate(temp)])

sorted_dict:
         {1: [2], 2: [], 3: [1], 4: [5], 5: [4, 5]}


0

私の提案はこれです。これにより、ディクテーションをソートしたり、アイテムを追加するときにディクテーションをソートしたままにしたりできるため、将来アイテムを追加する必要があるかもしれません。

作業を進めながらdict、ゼロから構築します。キーのリストを含む2番目のデータ構造、リストを用意します。bisectパッケージにはinsort関数があり、ソートされたリストに挿入したり、dictに完全に入力した後でリストをソートしたりできます。さて、dictを反復処理するときは、代わりにリストを反復処理して、(ソート用に作成されていない)dict構造の表現を気にすることなく、各キーに順番にアクセスします。


-1
l = dict.keys()
l2 = l
l2.append(0)
l3 = []
for repeater in range(0, len(l)):
    smallnum = float("inf")
    for listitem in l2:
        if listitem < smallnum:
            smallnum = listitem
    l2.remove(smallnum)
    l3.append(smallnum)
l3.remove(0)
l = l3

for listitem in l:
    print(listitem)

3
他に14の答えがあります。あなたのコードを少し説明して、なぜそれが他の解決策よりも優れているのでしょうか?
FelixSFD 2016年

反対投票-意味のない短い変数名l、l2、l3を含むかなり読みにくいコード。python標準関数の知識がない間接的で非効率的なアルゴリズムの試みのようであり、いずれの場合も、元の投稿の小さな例でテストすると機能しません。
レプトンキャプテン、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.