6 ответов:
если
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вернет iterable dict view object, а не список. Нам нужно обернуть вызов в список, чтобы сделать индексацию возможной>>> items = list(d.items()) >>> items [('foo', 'python'), ('bar', 'spam')] >>> items[0] ('foo', 'python') >>> items[1] ('bar', 'spam')
вам нужно использовать OrderedDict или вы специально хотите тип карты, который упорядочен каким-то образом с быстрым позиционным индексированием? Если последнее, то рассмотрим один из многих отсортированных типов dict Python (который упорядочивает пары ключ-значение на основе порядка сортировки ключей). Некоторые реализации также поддерживают быструю индексацию. Например, 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, без создания списка:
>>> from collections import OrderedDict >>> >>> d = OrderedDict() >>> d["foo"] = "one" >>> d["bar"] = "two" >>> d["baz"] = "three" >>> >>> d.iteritems().next() ('foo', 'one')(в первый раз, когда вы говорите "следующий ()", это действительно означает "первый.")
в моем неофициальном тесте на Python 2.7,
iteritems().next()с небольшим OrderedDict только немного быстрее, чемitems()[0]. С OrderedDict из 10 000 записей,iteritems().next()был примерно в 200 раз быстрее, чемitems()[0].но если вы сохраните элементы () список один раз, а затем использовать список много, что может быть быстрее. Или если вы неоднократно { создаете итератор iteritems () и шагаете через него к нужной позиции }, это может быть медленнее.
Это значительно более эффективно использовать IndexedOrderedDict.
после комментария Никласа, я сделал тест на 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 loopIndexedOrderedDict ~100 раз быстрее в индексации элементов в определенном положении в этом конкретном случае.
это сообщество Вики пытается собрать существующие ответы.
Python 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"The 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 имеет те же два основных параметра (list vs generator), но методы 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. Но Раймонд Хеттингер-это следующая лучшая вещь (и смешнее), и он делает довольно весомые аргументы словари, которые будут заказаны в течение очень долгого времени.
Так что теперь легко создавать фрагменты словаря:
test_dict = { 'first': 1, 'second': 2, 'third': 3, 'fourth': 4 } list(test_dict.items())[:2]
Comments