次のコードがあるとしましょう:
import collections
d = collections.OrderedDict()
d['foo'] = 'python'
d['bar'] = 'spam'
次のように、番号を付けてアイテムにアクセスする方法はありますか?
d(0) #foo's Output
d(1) #bar's Output
次のコードがあるとしましょう:
import collections
d = collections.OrderedDict()
d['foo'] = 'python'
d['bar'] = 'spam'
次のように、番号を付けてアイテムにアクセスする方法はありますか?
d(0) #foo's Output
d(1) #bar's Output
次のOrderedDict()
ように(キー、値)ペアのタプルを取得することにより、インデックスを作成することで要素に簡単にアクセスできます
>>> 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')
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'
リストを作成せずに 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]
. 10,000 エントリの OrderedDict では、next(iter(d.items()))
より約 200 倍高速items()[0]
でした。
しかし、items() リストを一度保存してから、そのリストを何度も使用すると、より高速になる可能性があります。または、{ items() イテレータを作成し、それを目的の位置までステップ実行する} を繰り返すと、処理が遅くなる可能性があります。
このコミュニティ ウィキは、既存の回答を収集しようとします。
パイソン 2.7
Python 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 |
+--------+-----------+----------------+---------+
パイソン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 に組み込まれている名前付きタプルを使用してください。考えられるユースケースは、いくつかの定数データを保存し、インデックス作成とキーの指定の両方によってプログラム全体でアクセスする場合です。
import collections
ordered_keys = ['foo', 'bar']
D = collections.namedtuple('D', ordered_keys)
d = D(foo='python', bar='spam')
d[0] # result: python
d[1] # result: spam
d.foo # result: python
d.bar # result: spam
またはより良い:
getattr(d, 'foo') # result: python
getattr(d, 'bar') # result: spam