web-dev-qa-db-ja.com

Python dictは整数がキーとして自然にソートされるので?

整数をキーとして使用するPython dictを作成した場合、dictを反復すると、キーの値に従ってアイテムが順番に取得されると安全に想定できますか?

つまり

my_dict = {}
for x in range(0,100):
  my_dict[x] = str(x)

for item in my_dict.items():
  print item

常にキー値の順にリストを印刷する結果になりますか?

17
user3067927

つまり、いいえ。辞書はキーのハッシュを配列のインデックスとして使用し、intはそれ自体の値にハッシュするため、キーが整数の場合、挿入された値はキーの順になると推測していることにお気づきでしょう。そのステートメントの最初の2つの部分は真実ですが、推論は文書化されていない副作用としてもそうではありません。 dictキーは、キーのハッシュから派生ですが、完全なハッシュではありません。つまり、整数キーを使用しても、2つの値が同じ場所で衝突する可能性があるため(または「順序が正しくない」ハッシュから派生した値が含まれる可能性があるため)、順序どおりに挿入されず、結果としてキーが順序どおりに挿入されない可能性があります。 dict。

基本的に、dictの内部ストレージ配列のインデックスは、キーのハッシュからの下位ビットの数であると考えてください。ある数値が他の数値よりも大きいからといって、その数値から切り捨てられた下位ビットが大きくなる、または異なる場合さえあります。

12
Silas Ray

いいえ、Python辞書には、キーの値に関係なく、固有の順序はありません。順序が必要な場合は、配列またはリストに固執するか、より適切です-pandasを確認してください。辞書と同様の機能で、キーの値やその他の多くの強力な機能( http://pandas.pydata.org/pandas-docs/stable/10min.html )で呼び出すことができます。

6
qmorgan

いいえ、できません。常に順序どおりに反復処理を行う場合は並べ替えます。

そうは思いません。確実に注文するには、collections.OrderedDictを使用する必要があります。ただし、これにより、エントリが追加された順にソートされます。

2
fuesika

Python辞書は、意味のある順序で並べられていません。それらはハッシュテーブルです。

Pythonにはcollections.OrderedDictが付属していますが、これはキーの順序ではなく、挿入順にソートされます。

以下は、キーでソートする2つの辞書のようなモジュールです。

https://pypi.python.org/pypi/treap/

https://pypi.python.org/pypi/red-black-tree-mod/

トレッドは赤黒木より平均して速いが、赤黒木は操作時間の標準偏差が低いと言う人もいます。他の人はこれを疑問視しますが、私のテストでは前者は真実であることが証明されました。

Treapとred-black treesは、ほとんどすべてをO(logn)時間で実行しますが、キーの順序を常に保ちます。Python辞書はO(1)ほとんどの操作です。ただし、すべてのキーを順番に取得することは、O(n) treapとred-black treesの場合は、O(nlogn)辞書の場合。

どちらを使用すべきですか?

  1. ループでソートしている場合は、おそらく、木か赤黒の木を使うほうがよいでしょう。
  2. プログラムまたは何かの終わりに一度ソートしている場合は、おそらくlist_ = list(dict_);の方が良いでしょう。 list_.sort()
  3. 設定ファイルなどからの入力の順序を保持している場合は、おそらくOrderedDictが最適です。

HTH

1
dstromberg

パーティーにはかなり遅れますが、私のように、[お気に入りの検索エンジン]でこのページに出会ったことがあれば、私はあなたに朗報を送りたいと思います。

Python dictsが自然にソートされることは決してありませんが、あたかもそれらがそうであるかのようにそれらを使用することは簡単です。キーが実際には整数であると仮定すると、単にDsortedに渡すだけです。そのような組み込み:

_for index, item in sorted(D.items()):
    print("index:", index, "item:", item)
_

D.items()は、_dict_items_メソッドでクラス___iter___を返します。これは、forまたはinステートメントによって呼び出されると、反復子を返し、反復可能なキーと値のペアを生成します他のイテラブルのように。

sortedはイテレータを使用してリストを返すため、_D = {1: "alpha", 3: "charlie", 2: "bravo"}_の場合、sortedによって返されるのはソートされたリスト[(1, "alpha"), (2, "bravo"), (3, "charlie")]です。

特定の要素で並べ替えることもできます。

_sorted(D.items(), key=lambda x: x[1])
_

または、他の任意の、さらには非決定的なソート基準によって:

_sorted(D.items(), lambda _: random.randint(0, 100))
_

辞書からのリストの構築は、時間と空間での操作O(n)であり、PythonのソートアルゴリズムTimsortは非常に効率的です(O(n log- n)平均的な場合)、したがって、実際のユースケースの大部分では、実行時のパフォーマンスは心配する価値のあるものではありません。

0
benas