Accessing items in an collections.OrderedDict by index

后端 未结 9 1589
我寻月下人不归
我寻月下人不归 2020-11-28 19:41

Lets say I have the following code:

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

Is there

9条回答
  •  攒了一身酷
    2020-11-28 20:25

    This community wiki attempts to collect existing answers.

    Python 2.7

    In python 2, the keys(), values(), and items() functions of OrderedDict return lists. Using values as an example, the simplest way is

    d.values()[0]  # "python"
    d.values()[1]  # "spam"
    

    For large collections where you only care about a single index, you can avoid creating the full list using the generator versions, iterkeys, itervalues and iteritems:

    import itertools
    next(itertools.islice(d.itervalues(), 0, 1))  # "python"
    next(itertools.islice(d.itervalues(), 1, 2))  # "spam"
    

    The indexed.py package provides IndexedOrderedDict, which is designed for this use case and will be the fastest option.

    from indexed import IndexedOrderedDict
    d = IndexedOrderedDict({'foo':'python','bar':'spam'})
    d.values()[0]  # "python"
    d.values()[1]  # "spam"
    

    Using itervalues can be considerably faster for large dictionaries with random access:

    $ 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 has the same two basic options (list vs generator), but the dict methods return generators by default.

    List method:

    list(d.values())[0]  # "python"
    list(d.values())[1]  # "spam"
    

    Generator method:

    import itertools
    next(itertools.islice(d.values(), 0, 1))  # "python"
    next(itertools.islice(d.values(), 1, 2))  # "spam"
    

    Python 3 dictionaries are an order of magnitude faster than python 2 and have similar speedups for using generators.

    +--------+-----------+----------------+---------+
    |  size  | list (ms) | generator (ms) | indexed |
    +--------+-----------+----------------+---------+
    |   1000 | .0316     | .0165          | .00262  |
    |  10000 | .288      | .166           | .00294  |
    | 100000 | 3.53      | 1.48           | .00332  |
    +--------+-----------+----------------+---------+
    

提交回复
热议问题