我正在使用一个OrderedDict来随机访问一个列表,但现在想要获取与我当前拥有的项相邻的下一项
:
foo = OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
apple = foo['apple']
我如何仅使用foo
和apple
获取香蕉?
我正在使用一个OrderedDict来随机访问一个列表,但现在想要获取与我当前拥有的项相邻的下一项
:
foo = OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
apple = foo['apple']
我如何仅使用foo
和apple
获取香蕉?
>>> class MyOrderedDict(OrderedDict):
... def next_key(self, key):
... next = self._OrderedDict__map[key][1]
... if next is self._OrderedDict__root:
... raise ValueError("{!r} is the last key".format(key))
... return next[2]
... def first_key(self):
... for key in self: return key
... raise ValueError("OrderedDict() is empty")
...
>>> od = MyOrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
>>> od.next_key("apple")
'banana'
>>> od.next_key("banana")
'orange'
>>> od.next_key("orange")
'pear'
>>> od.next_key("pear")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in next_key
ValueError: 'pear' is the last key
>>> od.first_key()
'apple'
OrderedDict
的实现略有改变(请参见此处)。链接列表上的元素现在是一个名为 _Link
的虚拟类的对象。不再使用 self._OrderedDict__map[key][1]
访问,而应该使用 self._OrderedDict__map[key].next
。 - Andrés我不敢想象在一个很大的列表中这样做会有多慢,但这是我目前想到的唯一方法...
>>> foo.items()[foo.keys().index('apple') + 1]
('banana', 3)
编辑:
这个例子有些牵强;我实际的集合是按日期键入的。如果我需要在今天
之后获取条目,则可以使用dropwhile解决方法...
>>> foo = OrderedDict([(datetime.date(2000,1,1), 4), (datetime.date(2000,5,23), 3), datetime.date(2000,10,1), 2), (datetime.date(2000,12,31), 1)])
>>> today = datetime.date(2000,1,30)
>>> foo.items()[foo.keys().index((itertools.dropwhile(lambda d: d<today, foo)).next())]
(datetime.date(2000, 5, 23), 3)
相当冗长。
Python 3.X
dict.items 会返回一个可迭代的字典视图对象,而不是列表。为了使索引操作成为可能,我们需要将其包装在一个列表中:
>>> from collections import OrderedDict
>>>
>>> foo = OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
>>>
>>> def next_item(odic, key):
... return list(odic)[list(odic.keys()).index(key) + 1]
...
>>> next = next_item(foo, 'apple')
>>> print(next, foo[next])
banana 3
从您的代码进行了修改,我认为这种方式会更好一些:
import collections as co
import datetime as dt
import itertools as it
foo = co.OrderedDict([
(dt.date(2000,1,1), 4),
(dt.date(2000,5,23), 3),
(dt.date(2000,10,1), 2),
(dt.date(2000,12,31), 1)
])
today = dt.date(2000,1,30)
fooiter = it.dropwhile(lambda d: d <= today, foo)
print next(fooiter)
print list(fooiter)
基本上,在正确的位置拥有迭代器已经足够了。
从任何位置开始迭代会很酷,但不确定是否可行。需要一些思考。
OrderedDict
对于这个似乎太简单了。也许可怕的一行代码会起作用?foo[(lambda keys: keys[(keys.index('pear') + 1) % len(keys)])(foo.keys())]
- Blender