回答:
その場合、OrderedDict()
次のように(key、value)ペアのタプルを取得することにより、インデックスを作成することで要素に簡単にアクセスできます。
>>> import collections
>>> d = collections.OrderedDict()
>>> d['foo'] = 'python'
>>> d['bar'] = 'spam'
>>> d.items()
[('foo', 'python'), ('bar', 'spam')]
>>> d.items()[0]
('foo', 'python')
>>> d.items()[1]
('bar', 'spam')
Python 3.Xに関する注意
dict.items
リストではなく、反復可能なdictビューオブジェクトを返します。インデックス作成を可能にするために、呼び出しをリストにラップする必要があります
>>> items = list(d.items())
>>> items
[('foo', 'python'), ('bar', 'spam')]
>>> items[0]
('foo', 'python')
>>> items[1]
('bar', 'spam')
list(d.items())
list(d.items())
、を使用next(islice(d.items(), 1))
してのメモリオーバーヘッドを回避できます('bar', 'spam')
OrderedDictを使用する必要がありますか、それとも、高速な位置インデックスを使用して何らかの方法で順序付けされたマップのようなタイプが必要ですか?後者の場合は、Pythonの多くのソートされたdictタイプ(キーのソート順序に基づいてキーと値のペアを順序付ける)の1つを検討してください。一部の実装では、高速なインデックス作成もサポートされています。たとえば、sortedcontainersプロジェクトには、この目的のためだけにSortedDictタイプがあります。
>>> from sortedcontainers import SortedDict
>>> sd = SortedDict()
>>> sd['foo'] = 'python'
>>> sd['bar'] = 'spam'
>>> print sd.iloc[0] # Note that 'bar' comes before 'foo' in sort order.
'bar'
>>> # If you want the value, then simple do a key lookup:
>>> print sd[sd.iloc[1]]
'python'
SortedDict
、比較を回避するためにキー関数を使用することもできます。のように:SortedDict(lambda key: 0, ...)
。その後、キーは並べ替えられませんが、安定した順序が維持され、インデックスに登録できます。
リストを作成せずにOrderedDict の最初のエントリ(またはその近く)が必要な場合の特殊なケースを次に示します。(これはPython 3に更新されました):
>>> from collections import OrderedDict
>>>
>>> d = OrderedDict()
>>> d["foo"] = "one"
>>> d["bar"] = "two"
>>> d["baz"] = "three"
>>> next(iter(d.items()))
('foo', 'one')
>>> next(iter(d.values()))
'one'
(初めて「next()」と言うときは、実際には「最初」を意味します。)
私の非公式のテストでnext(iter(d.items()))
は、小さなOrderedDictを使用した場合は、よりも少しだけ高速ですitems()[0]
。OrderedDictが10,000エントリで、のnext(iter(d.items()))
約200倍の速さitems()[0]
でした。
しかし、あなたは一度の項目()のリストを保存し、より高速な可能性があり、リストに多くを、使用している場合。または、{items()イテレータを繰り返し作成し、目的の位置までステップスルーする}と、速度が遅くなる可能性があります。
OrderedDict
はiteritems()
メソッドがないため、最初のアイテムを取得するには、次の操作を行う必要がありますnext(iter(d.items()))
。
d.items()
ではイテレータではないように見えるので、前のイテレータは役に立ちませんか?それでも完全なリストを返します:(
odict_iterator
れ、IRC #pythonでリストのコピーが作成されないことが確認されました。
パッケージからIndexedOrderedDictを使用する方が劇的に効率的indexed
です。
Niklasのコメントに続いて、私はOrderedDictとIndexedOrderedDictで1000エントリのベンチマークを行いました。
In [1]: from numpy import *
In [2]: from indexed import IndexedOrderedDict
In [3]: id=IndexedOrderedDict(zip(arange(1000),random.random(1000)))
In [4]: timeit id.keys()[56]
1000000 loops, best of 3: 969 ns per loop
In [8]: from collections import OrderedDict
In [9]: od=OrderedDict(zip(arange(1000),random.random(1000)))
In [10]: timeit od.keys()[56]
10000 loops, best of 3: 104 µs per loop
IndexedOrderedDictは、この特定のケースで特定の位置にある要素のインデックス作成で最大 100倍高速です。
indexed.py
代わりにインストールしてみてくださいindexed
。
このコミュニティwikiは、既存の回答を収集しようとします。
Python 2.7
パイソン2では、keys()
、values()
、とitems()
の機能OrderedDict
リターンリスト。values
例として使用すると、最も簡単な方法は
d.values()[0] # "python"
d.values()[1] # "spam"
あなただけの単一のインデックスを気に大規模なコレクションのために、あなたは、発電機のバージョンを使用して完全なリストを作成しないようにすることができiterkeys
、itervalues
そしてiteritems
:
import itertools
next(itertools.islice(d.itervalues(), 0, 1)) # "python"
next(itertools.islice(d.itervalues(), 1, 2)) # "spam"
indexed.pyパッケージが提供しIndexedOrderedDict
、このユースケースのために設計されており、最速の選択肢になります、。
from indexed import IndexedOrderedDict
d = IndexedOrderedDict({'foo':'python','bar':'spam'})
d.values()[0] # "python"
d.values()[1] # "spam"
itervaluesを使用すると、ランダムアクセスを持つ大規模なディクショナリの場合、かなり高速になります。
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 1000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i:i+1]'
1000 loops, best of 3: 259 usec per loop
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 10000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i:i+1]'
100 loops, best of 3: 2.3 msec per loop
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 100000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i:i+1]'
10 loops, best of 3: 24.5 msec per loop
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 1000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); next(itertools.islice(d.itervalues(), i, i+1))'
10000 loops, best of 3: 118 usec per loop
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 10000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); next(itertools.islice(d.itervalues(), i, i+1))'
1000 loops, best of 3: 1.26 msec per loop
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 100000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); next(itertools.islice(d.itervalues(), i, i+1))'
100 loops, best of 3: 10.9 msec per loop
$ python2 -m timeit -s 'from indexed import IndexedOrderedDict; from random import randint; size = 1000; d = IndexedOrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i]'
100000 loops, best of 3: 2.19 usec per loop
$ python2 -m timeit -s 'from indexed import IndexedOrderedDict; from random import randint; size = 10000; d = IndexedOrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i]'
100000 loops, best of 3: 2.24 usec per loop
$ python2 -m timeit -s 'from indexed import IndexedOrderedDict; from random import randint; size = 100000; d = IndexedOrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i]'
100000 loops, best of 3: 2.61 usec per loop
+--------+-----------+----------------+---------+
| size | list (ms) | generator (ms) | indexed |
+--------+-----------+----------------+---------+
| 1000 | .259 | .118 | .00219 |
| 10000 | 2.3 | 1.26 | .00224 |
| 100000 | 24.5 | 10.9 | .00261 |
+--------+-----------+----------------+---------+
Python 3.6
Python 3には同じ2つの基本オプション(リストとジェネレーター)がありますが、dictメソッドはデフォルトでジェネレーターを返します。
リスト方式:
list(d.values())[0] # "python"
list(d.values())[1] # "spam"
ジェネレーター法:
import itertools
next(itertools.islice(d.values(), 0, 1)) # "python"
next(itertools.islice(d.values(), 1, 2)) # "spam"
Python 3辞書は、python 2よりも桁違いに高速で、ジェネレーターを使用する場合と同様の高速化があります。
+--------+-----------+----------------+---------+
| size | list (ms) | generator (ms) | indexed |
+--------+-----------+----------------+---------+
| 1000 | .0316 | .0165 | .00262 |
| 10000 | .288 | .166 | .00294 |
| 100000 | 3.53 | 1.48 | .00332 |
+--------+-----------+----------------+---------+
それは新しい時代であり、Python 3.6.1で辞書はその順序を保持します。BDFLの承認が必要になるため、これらのセマンティクスは明示的ではありません。しかし、レイモンドヘッティンガーは2番目に優れた(そしておかしな)人物であり、辞書が非常に長い間注文されるというかなり強い主張をします。
したがって、辞書のスライスを作成するのは簡単です。
test_dict = {
'first': 1,
'second': 2,
'third': 3,
'fourth': 4
}
list(test_dict.items())[:2]
注:辞書の挿入順の保持は、Python 3.7で公式になりました。
OrderedDict()の場合、次のように(key、value)ペアのタプルを取得するか、 '。values()'を使用してインデックスを作成することで要素にアクセスできます。
>>> import collections
>>> d = collections.OrderedDict()
>>> d['foo'] = 'python'
>>> d['bar'] = 'spam'
>>> d.items()
[('foo', 'python'), ('bar', 'spam')]
>>>d.values()
odict_values(['python','spam'])
>>>list(d.values())
['python','spam']
items
メソッドはリストではなく相互に対応するディクショナリビューオブジェクトを返し、スライスやインデックス作成をサポートしていないことに注意してください。したがって、最初にリストに変換する必要があります。docs.python.org/3.3/library/stdtypes.html#dict-views