Допустим, у меня есть следующий код:
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')
items
метод возвращает объект представления целевого словаря, а не список, и не поддерживает нарезку или индексирование. Так что сначала вам нужно превратить его в список. docs.python.org/3.3/library/stdtypes.html#dict-viewslist(d.items())
list(d.items())
, используяnext(islice(d.items(), 1))
to get('bar', 'spam')
Вам нужно использовать OrderedDict или вам нужен тип, похожий на карту, который каким-то образом упорядочен с быстрой позиционной индексацией? В последнем случае рассмотрите один из множества сортированных типов словаря 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'
источник
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(iter(d.items()))
с небольшим OrderedDict лишь немного быстрее, чемitems()[0]
. С OrderedDict из 10 000 записей онnext(iter(d.items()))
был примерно в 200 раз быстрее, чемitems()[0]
.НО, если вы сохраните список items () один раз, а затем будете использовать его часто, это может быть быстрее. Или, если вы несколько раз {создаете итератор items () и переходите через него в нужную позицию}, это может быть медленнее.
источник
OrderedDict
s не имеетiteritems()
методы, так что вам нужно будет сделать следующее, чтобы получить первый элемент:next(iter(d.items()))
.d.items()
вроде итератора нет, так что iter впереди не поможет? Он все равно вернет полный список :(odict_iterator
и мне подтвердили на IRC #python, что это не создает копию списка.Значительно эффективнее использовать IndexedOrderedDict из
indexed
пакета.Следуя комментарию Никласа, я провел тест для 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
.Эта вики сообщества пытается собрать существующие ответы.
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"
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 имеет те же две основные опции (список и генератор), но методы 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]
Примечание. Сохранение порядка вставки словаря теперь официально в Python 3.7 .
источник
Если вы имеете дело с заранее известным фиксированным количеством ключей , используйте вместо этого встроенные именованные кортежи 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
источник
Если вы
pandas
установили, вы можете преобразовать заказанный диктант в пандSeries
. Это позволит произвольный доступ к элементам словаря.>>> import collections >>> import pandas as pd >>> d = collections.OrderedDict() >>> d['foo'] = 'python' >>> d['bar'] = 'spam' >>> s = pd.Series(d) >>> s['bar'] spam >>> s.iloc[1] spam >>> s.index[1] bar
источник
для OrderedDict () вы можете получить доступ к элементам путем индексации, получая кортежи пар (ключ, значение) следующим образом или используя '.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']
источник