Answers:
如果是OrderedDict()
,则可以通过获取(key,value)对的元组的索引来轻松访问元素,如下所示
>>> 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')
list(d.items())
list(d.items())
通过next(islice(d.items(), 1))
获取以下内容来避免的内存开销:('bar', 'spam')
您是否必须使用OrderedDict还是特别想要以快速位置索引以某种方式排序的类似地图的类型?如果是后者,则考虑使用Python多种排序的dict类型之一(根据键的排序顺序对键值对进行排序)。一些实现还支持快速索引。例如,为此目的,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()”时,它的意思实际上是“第一”。)
在我的非正式测试中,next(iter(d.items()))
使用小OrderedDict仅比快一点items()[0]
。使用10,000个条目的OrderedDict,next(iter(d.items()))
比快200倍items()[0]
。
但是,如果您只保存items()列表一次,然后大量使用该列表,那可能会更快。或者,如果您反复{创建一个items()迭代器并将其逐步移动到所需位置},那可能会更慢。
OrderedDict
没有iteritems()
方法,因此您需要执行以下操作才能获得第一项:next(iter(d.items()))
。
d.items()
中似乎不是迭代器,所以前面的迭代器无济于事?它仍然会返回完整列表:(
odict_iterator
,并在IRC #python上向我确认这没有复制列表。
从包中使用IndexedOrderedDict会大大提高效率indexed
。
根据Niklas的评论,我对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
。
该社区Wiki尝试收集现有答案。
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具有相同的两个基本选项(列表vs生成器),但是默认情况下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批准。但是雷蒙德·海廷格(Raymond Hettinger)是下一个最好的东西(而且更有趣),他提出了一个非常有力的理由,那就是字典将在很长一段时间内被订购。
因此,现在很容易创建字典的切片:
test_dict = {
'first': 1,
'second': 2,
'third': 3,
'fourth': 4
}
list(test_dict.items())[:2]
注意:现在,字典插入顺序保留在Python 3.7中是正式的。
对于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']
items
方法返回一个可交互的字典视图对象而不是列表,并且不支持切片或索引。因此,您必须首先将其转换为列表。docs.python.org/3.3/library/stdtypes.html#dict-views