dictをOrderedDictに変換する


138

collections.OrderedDictクラスの使用に問題があります。私はRaspbian、Raspberry PiのDebianディストリビューションでPython 2.7を使用しています。私はテキストアドベンチャーの比較(並べて)のために2つの辞書を印刷しようとしています。順序は正確に比較するために不可欠です。私が何を試そうとも、辞書は通常の順序どおりに印刷されません。

RPiで実行すると、次のようになります。

import collections

ship = {"NAME": "Albatross",
         "HP":50,
         "BLASTERS":13,
         "THRUSTERS":18,
         "PRICE":250}

ship = collections.OrderedDict(ship)

print ship
# OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])

関数呼び出しを出力し、キーと値グループをネストされたリストに入れているため、明らかに何かが正しくありません...

これは私が私のPCで同様の何かを実行して得たものです:

import collections

Joe = {"Age": 28, "Race": "Latino", "Job": "Nurse"}
Bob = {"Age": 25, "Race": "White", "Job": "Mechanic", "Random": "stuff"}

#Just for clarity:
Joe = collections.OrderedDict(Joe)
Bob = collections.OrderedDict(Bob)

print Joe
# OrderedDict([('Age', 28), ('Race', 'Latino'), ('Job', 'Nurse')])
print Bob
# OrderedDict([('Age', 25), ('Race', 'White'), ('Job', 'Mechanic'), ('Random', 'stuff')])

今回は順調ですが、他の物を印刷してはいけませんよね?(リストに入れて、関数呼び出しを表示します。)

エラーはどこにありますか?Pythonのpiバージョンとは関係ありません。これは、Linuxバージョンであるためです。


3
注:OrderedDictは、英数字のキー順ではなく、挿入順にソートされています。
el.pescado 2017

回答:


214

最初に辞書を作成してから、その辞書をに渡しOrderedDictます。Pythonバージョン3.6 (*)未満の場合、その時点で、順序は正しくありません。dict本質的に注文されていません。

代わりにタプルのシーケンスを渡します:

ship = [("NAME", "Albatross"),
        ("HP", 50),
        ("BLASTERS", 13),
        ("THRUSTERS", 18),
        ("PRICE", 250)]
ship = collections.OrderedDict(ship)

印刷したときに表示されるOrderedDictのは表現であり、完全に正しいものです。OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])は、の内容を再現可能な表現で示していますOrderedDict


(*):CPython 3.6の実装では、dict型が更新され、メモリ効率の高い内部構造を使用するように更新されました。これにより、挿入順序が保持されるという副作用があり、質問に示されたコードは問題なく機能します。Python 3.7以降、すべてのPython実装がこの動作に従う必要があることを要求するようにPython言語仕様が更新されました。詳細と、特定のケースで引き続きを使用する理由については、私の別の回答を参照してくださいOrderedDict()


OrderedDictが辞書を作成してくれますか?また、再現可能な表現なしで印刷するには、OrderedDictが使用されている変数だけを印刷できますか?すなわち: print ship ?? ありがとう:)
pythonpiboy

3
質問:あなたが説明した方法で、OrderedDictは順序付けられた「リスト」を作成しています。それは目的を打ち負かさないのでは?キーと値を持つ辞書ではなく、要素のリストのみを作成しています...
pythonpiboy

9
タイプは両方のように機能します。順序を保持するマッピング。オーダー付きで作成するには、アイテムを順番に与える必要があります。標準のdict(PyPIまたはPython 3.6+以外のもの)ではそれができないため、代わりにタプルのリストを指定します。いったんOrderedDict作成されたことがある辞書。
Martijn Pieters

4
混乱のように聞こえるのは、OrderedDictが順序を保持するだけでなく、順序を「適用する」と仮定したためです。作成時に入力をソートするか、またはitems()関数がいつ挿入されたかに関係なくソートされた項目を返すと仮定しました。代わりに、指定した順序が保持されます。
whiterook6

2
@ whiterook6:ソートされた辞書ではありません。これは順序付けされた辞書であり、キーと値のペアの順序を記録して、それらのペアを並べ替えることができます。これを、順序付けられたシーケンスであるリストと比較してください。
Martijn Pieters

36

dictが定義されているコードのこの部分を編集できない場合でも、次のように、いつでも好きな方法で注文できます。

from collections import OrderedDict

order_of_keys = ["key1", "key2", "key3", "key4", "key5"]
list_of_tuples = [(key, your_dict[key]) for key in order_of_keys]
your_dict = OrderedDict(list_of_tuples)

11

ほとんどの場合、ASCなどの一般的な注文ではなく、カスタム注文が必要なときにOrderedDictを使用します。

ここに提案された解決策があります:

import collections
ship = {"NAME": "Albatross",
         "HP":50,
         "BLASTERS":13,
         "THRUSTERS":18,
         "PRICE":250}

ship = collections.OrderedDict(ship)

print ship


new_dict = collections.OrderedDict()
new_dict["NAME"]=ship["NAME"]
new_dict["HP"]=ship["HP"]
new_dict["BLASTERS"]=ship["BLASTERS"]
new_dict["THRUSTERS"]=ship["THRUSTERS"]
new_dict["PRICE"]=ship["PRICE"]


print new_dict

これは出力されます:

OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])
OrderedDict([('NAME', 'Albatross'), ('HP', 50), ('BLASTERS', 13), ('THRUSTERS', 18), ('PRICE', 250)])

:ソートされた新しい辞書は、エントリが削除されてもソート順を維持します。しかし、新しいキーが追加されると、キーは最後に追加され、ソートは維持されません。(公式ドキュメント


2

dict.items();を使用します。次のように簡単にすることができます。

ship = collections.OrderedDict(ship.items())
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.