112

Вопрос по python – Доступ к элементам в коллекциях. OrderDict по индексу

Допустим, у меня есть следующий код:

import collections
d = collections.OrderedDict()
d['foo'] = 'python'
d['bar'] = 'spam'

Есть ли способ получить доступ к элементам в пронумерованном виде, например:

d(0) #foo's Output
d(1) #bar's Output
  • Error: User Rate Limit Exceededgithub.com/niklasf/indexed.py

    от
  • Error: User Rate Limit Exceededd.items()Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceededlist(d.items())

    от
  • Error: User Rate Limit Exceededlist(d.items())Error: User Rate Limit Exceedednext(islice(d.items(), 1))Error: User Rate Limit Exceeded('bar', 'spam')

    от
  • Error: User Rate Limit ExceededOrderedDictError: User Rate Limit Exceedediteritems()Error: User Rate Limit Exceedednext(iter(d.items())).

    от
  • Error: User Rate Limit ExceededitemsError: User Rate Limit Exceededdocs.python.org/3.3/library/stdtypes.html#dict-views

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit ExceededSortedDictError: User Rate Limit ExceededSortedDict(lambda key: 0, ...)Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceededodict_iteratorError: User Rate Limit Exceeded

    от
7 ответов
  • 0

    для OrderedDict () вы можете получить доступ к элементам путем индекса

    ции, получив кортежи пар (ключ, значение) следующим образом или используя & apos; .values () & apos;

    >>> 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']
    

  • 23

    Нужно ли вам использовать 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'
    

  • 13

    Это значительно более эффективно использовать

    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 раз быстрее выполняется индексация элементов в определенной позиции.

  • 141

    Если это

    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')
    

    Note for Python 3.X

    dict.items вернетповторяемый объект просмотра а не список. Нам нужно обернуть вызов в список, чтобы сделать возможной индексацию

    >>> items = list(d.items())
    >>> items
    [('foo', 'python'), ('bar', 'spam')]
    >>> items[0]
    ('foo', 'python')
    >>> items[1]
    ('bar', 'spam')
    

  • 16

    Вот особый случай, если вы хотитеfirst 

    запись (или близкая к ней) в OrderedDict, без создания списка:

    >>> from collections import OrderedDict
    >>> 
    >>> d = OrderedDict()
    >>> d["foo"] = "one"
    >>> d["bar"] = "two"
    >>> d["baz"] = "three"
    >>> 
    >>> d.iteritems().next()
    ('foo', 'one')
    

    (Когда вы в первый раз говорите «next ()», это действительно означает «сначала».)

    В моем неформальном тесте на Python 2.7iteritems().next() с небольшим OrderedDict только чуть-чуть быстрее, чемitems()[0], С OrderedDict 10000 записей,iteritems().next() был примерно в 200 раз быстрее, чемitems()[0].

    BUT если вы сохраните список items () один раз, а затем будете использовать его много, это может быть быстрее. Или, если вы неоднократно {создаете итератор iteritems () и переходите к нему в нужную вам позицию}, это может быть медленнее.

  • 7

    This community wiki attempts to collect existing answers.

    Python 2.7

    В питоне 2keys(), 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"
    

    Использование больших значений может быть значительно быстрее для больших словарей с произвольным доступом:

    $ 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  |
    +--------+-----------+----------------+---------+
    

  • 4

    Это новая эра

    и теперь словари Python 3.6.1 сохраняют свой порядок. Эта семантика не является явной, потому что это потребует одобрения BDFL. Но Раймонд Хеттингер - следующая лучшая вещь (и смешнее), и он делаетдовольно сильный случай что словари будут заказывать очень долго.

    Так что теперь легко создавать фрагменты словаря:

    test_dict = {
                    'first':  1,
                    'second': 2,
                    'third':  3,
                    'fourth': 4
                }
    
    list(test_dict.items())[:2]
    

    Note: Диктонарное сохранение порядка вставки теперьОфициальный в Python 3.7.