访问项目在一个ordereddict

比方说,我有以下代码:

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,或者你是否需要一个类似于地图的types,以快速位置索引的方式进行sorting? 如果是后者,那么考虑一下Python的许多sorting字典types(根据键sorting顺序对键值对进行sorting)。 一些实现也支持快速索引。 例如, sortedcontainers项目有一个SortedDicttypes就是为了这个目的。

 >>> 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中的第一个条目(或接近它)而不创build列表,那么这是一个特例:

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

(你第一次说“next()”,它的意思是“first”。)

在Python 2.7的非正式testing中,带有小OrderedDict的iteritems().next()只比items()[0]快一点点。 iteritems().next()items()[0]快200倍。

但是如果你保存items()列表一次,然后使用列表很多,这可能会更快。 或者,如果你反复{创build一个iteritems()迭代器并遍历它到你想要的位置},那可能会变慢。

使用IndexedOrderedDict会显着更高效。

在Niklas的评论之后,我已经对OrderedDictIndexedOrderedDict做了1000个条目的基准testing。

 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倍。

这是一个新的时代,Python 3.6.1字典现在保持其秩序。 这些语义并不明确,因为这需要BDFL的批准。 但是雷蒙德·海廷格(Raymond Hettinger)是下一个最好的(也是更有趣的),他是一个非常有力的例子 ,字典将被命令很长一段时间。

所以现在很容易创build一个词典的切片:

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

这个社区wiki试图收集现有的答案。

Python 2.7

在Python 2中, OrderedDictkeys()values()items()函数返回列表。 以values为例,最简单的方法是

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

对于只关注单个索引的大型集合,可以避免使用生成器版本, iterkeysitervaluesiteritems来创build完整列表:

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

indexed.py包提供了IndexedOrderedDict ,它是为这个用例而devise的,并且是最快的select。

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