初期データの順序を保持するようにコンストラクターを使用してOrderedDictを初期化する正しい方法は?


124

初期データの順序を保持するように順序付き辞書(OD)を初期化する正しい方法は何ですか?

from collections import OrderedDict

# Obviously wrong because regular dict loses order
d = OrderedDict({'b':2, 'a':1}) 

# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b',2), ('a', 1)])

# What about using a list comprehension, will 'd' preserve the order of 'l'
l = ['b', 'a', 'c', 'aa']
d = OrderedDict([(i,i) for i in l])

質問:

  • OrderedDictタプルのリストの順序を保持する、またはリストまたはリストのリストなどのタプルまたはタプルのタプルは、初期の時間(上記第2および第3の実施例)に渡されましたか?

  • OrderedDict実際に注文を維持しているかどうかを確認するにはどうすればよいですか?にdictは予測不可能な順序があるので、テストベクトルの最初の順序がdictの予測不可能な順序と同じである場合はどうでしょうか。たとえば、d = OrderedDict({'b':2, 'a':1})を書く代わりにd = OrderedDict({'a':1, 'b':2})、順序が保持されていると誤って結論付ける可能性があります。この場合、私dictはa がアルファベット順に並べられていることを発見しましたが、常にそうであるとは限りません。反例を使用して、データ構造が順序を保持するかどうかを検証する信頼できる方法は何ですか?

PS 参照用にここに残しておきます。「OrderedDictコンストラクターとupdate()メソッドはどちらもキーワード引数を受け入れますが、Pythonの関数呼び出しセマンティクスパスインキーワード引数は通常の順序付けされていない辞書を使用しているため、順序は失われます」

PPS:うまくいけば、将来的に、OrderedDictはkwargsの順序も保持するようになります(例1):http ://bugs.python.org/issue16991


10
(空ではない)dictを使用してOrderedDictを初期化するのは間違っていることは漠然と皮肉なことです...おそらくユーザーの意図に違反しているので、おそらく警告につながるはずです。
smci 2016

3
python3.6以降OrderDict(b=2, a=1)は、適切な方法でもあります。PEP 468を参照してください。
IvanaGyro

回答:


90

OrderedDictは、アクセスできるすべての注文を保持します。最後の2つの例のように、順序付けされたデータを初期化するためにデータを渡す唯一の方法は、キーと値のペアのリスト(より一般的には反復可能)を渡すことです。あなたがリンクしたドキュメントが言うように、OrderedDictコンストラクターがそれを見る前に削除されているため、キーワード引数またはdict引数を渡すとき、OrderedDictはどの順序にもアクセスできません。

最後の例でリスト内包表記を使用しても、何も変更されないことに注意してください。との間に違いはOrderedDict([(i,i) for i in l])ありませんOrderedDict([('b', 'b'), ('a', 'a'), ('c', 'c'), ('aa', 'aa')])。リスト内包が評価され、リストが作成されて渡されます。OrderedDictは、それがどのように作成されたかについて何も知りません。


74
# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b', 2), ('a', 1)])

はい、うまくいきます。定義により、リストは常にそれが表される方法で順序付けられます。これは、あまりにもリスト-理解のために行く、生成されたリストは、(から供給、それは決定論的になり、リストからすなわちソースをデータが提供されたのと同じ方法であるsetdictそんなに)。

OrderedDict実際に注文を維持しているかどうかを確認するにはどうすればよいですか。dictには予測不可能な順序があるので、テストベクトルが幸運にも、dictの予測不可能な順序と同じ初期順序を持っている場合はどうなりますか?。たとえば、d = OrderedDict({'b':2, 'a':1})を書く代わりにd = OrderedDict({'a':1, 'b':2})、順序が保持されていると誤って結論付ける可能性があります。この場合、私dictはa がアルファベット順になっていることを発見しましたが、常にそうであるとは限りません。つまり、カウンターの例を使用して、データ構造が順序を維持しているか、またはテストベクタが壊れるまで繰り返しテストベクトルを試行することで不足していないかを確認するための信頼できる方法は何ですか。

参照用に2タプルのソースリストを保持し、単体テストを行うときのテストケースのテストデータとして使用します。それらを繰り返し処理して、順序が維持されるようにします。


順序の確認について:dictの順序が予測できない場合、2タプルがdictの順序を壊すことを確認するにはどうすればよいですか?これは、データ構造に関する一般的な質問です。おそらく、この質問とは別の質問にする必要があります。
クリック

1
本質的に非決定論的なものを決定論的に破壊することはできません。
メタトースター2014

1
それで、そのようなことをテストするための正しいアプローチは何ですか?あなたは無期限に挑戦し続けますか?プログラマにとって順序は予測できませんが、それはハッシュマップであるため、「何らかの」アルゴリズムに従います。正しいテストでは、これに対抗する必要がありますか?
クリック

2
を参照してください__hash__。具体的にはstrタイプについて。
メタトースター2014

定義により、リストは常にそれが表される方法で順序付けられます。 これは私にとって重要な声明でした。リストをOrderedDictに変換するオーバーヘッドが生じないように、基本的には2タプルのリストを使用することにしましたOrderedDict。辞書ではなくリストのように要素をループするだけです。
Bobort
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.