web-dev-qa-db-ja.com

Pythonでは、ソートされたキーの順序で辞書を反復するにはどうすればよいですか?

次で終わる既存の関数があります。ここで、dは辞書です。

return d.iteritems()

指定された辞書のソートされていないイテレータを返します。ソートされた項目を通過するイテレータを返したいと思いますby by key。それ、どうやったら出来るの?

198
mike

これをあまり広範囲にテストしていませんが、Python 2.5.2で動作します。

>>> d = {"x":2, "h":15, "a":2222}
>>> it = iter(sorted(d.iteritems()))
>>> it.next()
('a', 2222)
>>> it.next()
('h', 15)
>>> it.next()
('x', 2)
>>>

イテレータの代わりにfor key, value in d.iteritems(): ...を実行することに慣れている場合、これは上記のソリューションでも動作します

>>> d = {"x":2, "h":15, "a":2222}
>>> for key, value in sorted(d.iteritems()):
>>>     print(key, value)
('a', 2222)
('h', 15)
('x', 2)
>>>

Python 3.xでは、d.items()の代わりにd.iteritems()を使用してイテレーターを返します。

161
Chris Cameron

sorted() 関数を使用します。

return sorted(dict.iteritems())

sorted()がリストを返すため、ソートされた結果の実際のイテレーターが必要な場合は、次を使用します。

return iter(sorted(dict.iteritems()))
80
Greg Hewgill

Dictのキーはハッシュテーブルに保存されているため、「自然な順序」、つまり擬似ランダムです。その他の順序は、辞書の消費者の概念です。

sort()は常に辞書ではなくリストを返します。 dict.items()(タプルのリストを生成する)を渡すと、ループで使用できるタプルのリスト[(k1、v1)、(k2、v2)、...]を返します。ある意味では辞書に似ていますが、とにかく辞書にはありません

foo = {
    'a':    1,
    'b':    2,
    'c':    3,
    }

print foo
>>> {'a': 1, 'c': 3, 'b': 2}

print foo.items()
>>> [('a', 1), ('c', 3), ('b', 2)]

print sorted(foo.items())
>>> [('a', 1), ('b', 2), ('c', 3)]

以下はループ内の辞書のように感じますが、そうではなく、k、vに展開されるタプルのリストです。

for k,v in sorted(foo.items()):
    print k, v

以下とほぼ同等:

for k in sorted(foo.keys()):
    print k, foo[k]
38
Peter Rowell

グレッグの答えは正しい。 Python 3.0では、やらなければならないことに注意してください。

sorted(dict.items())

iteritemsがなくなるため。

30
Claudiu

Python 2.7でもOrderedDictを使用できるようになりました。

>>> from collections import OrderedDict
>>> d = OrderedDict([('first', 1),
...                  ('second', 2),
...                  ('third', 3)])
>>> d.items()
[('first', 1), ('second', 2), ('third', 3)]

ここには、2.7バージョンの 新機能 ページと OrderedDict API があります。

6
Caumons

一般に、次のように辞書をソートできます。

for k in sorted(d):
    print k, d[k]

D.iteritems()の「ドロップイン置換」を持つ質問の特定のケースでは、次のような関数を追加します。

def sortdict(d, **opts):
    # **opts so any currently supported sorted() options can be passed
    for k in sorted(d, **opts):
        yield k, d[k]

そのため、終了行は

return dict.iteritems()

return sortdict(dict)

または

return sortdict(dict, reverse = True)
5
pythonlarry
>>> import heapq
>>> d = {"c": 2, "b": 9, "a": 4, "d": 8}
>>> def iter_sorted(d):
        keys = list(d)
        heapq.heapify(keys) # Transforms to heap in O(N) time
        while keys:
            k = heapq.heappop(keys) # takes O(log n) time
            yield (k, d[k])


>>> i = iter_sorted(d)
>>> for x in i:
        print x


('a', 4)
('b', 9)
('c', 2)
('d', 8)

このメソッドにはまだO(N log N)の並べ替えがありますが、短い線形ヒープ化の後、アイテムを並べ替えられた順序で生成し、リスト全体が必ずしも必要ではない場合に理論的にはより効率的になります。

4
jamylak

sortはリストを返します。したがって、それを反復しようとするとエラーになりますが、辞書を注文できないため、リストを処理する必要があります。

コードのより大きなコンテキストが何であるかはわかりませんが、結果のリストにイテレーターを追加してみてください。たぶんこのような?:

return iter(sorted(dict.iteritems()))

もちろん、ソートされた辞書がタプルのリストになったため、タプルを取得することになります

例:あなたの辞書は:{'a':1,'c':3,'b':2}ソートされていると言ってリストに変換します:

[('a',1),('b',2),('c',3)]

したがって、実際にリストを反復処理すると、この例では文字列と整数で構成されるタプルが返されますが、少なくともリストを反復処理することができます。

3
pcn

キーの順序ではなく、アイテムが挿入された順序でソートする場合は、Pythonの collections.OrderedDict を確認する必要があります。 (Python 3のみ)

3
gecco

CPython 2.xを使用しており、大きな辞書mydictがある場合、sortedはmydictのキーのソート済みリストを作成するため、sorted(mydict)の使用は遅くなります。

その場合は、CのsorteddictのC実装を含むordereddictパッケージをご覧ください。特に、辞書のライフタイムのさまざまな段階(要素数など)でキーのソートされたリストを複数回調べる必要がある場合。

http://anthon.home.xs4all.nl/Python/ordereddict/

2
Anthon