2012-09-08 10 views
8

estoy usando un OrderedDict de acceso aleatorio una lista, pero ahora quiere el artículo next en la lista de la que tengo:¿Cómo obtener el "siguiente" elemento en un OrderedDict?

foo = OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)]) 
apple = foo['apple'] 

¿Cómo consigo el plátano y utilizando sólo fooapple?

+1

'OrderedDict' parece ser demasiado simple para esto. ¿Tal vez un horrible one-liner funcionaría? 'foo [(llaves lambda: teclas [(keys.index ('pera') + 1)% len (teclas)]) (foo.keys())]' – Blender

Respuesta

7

Si estás bien con el acceso a aquellas partes de la aplicación OrderedDict que se mantienen intencionadamente privada:

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

Más que bien, es la idea que estaba esperando. –

+0

En python 3.4, la implementación de 'OrderedDict' cambió ligeramente (ver [aquí] (https://hg.python.org/cpython/file/01437956ea67/Lib/collections/__init__.py#l85)). Los elementos en la lista enlazada son ahora objetos de la clase ficticia '_Link'. En lugar de acceder a 'self._OrderedDict__map [key] [1]', se debe acceder a 'self._OrderedDict__map [key] .next'. –

+0

En python3.5 las cosas parecen haber cambiado aún más. La implementación de OrderedDict se mueve a C desde Python. Verifique [https://bugs.python.org/issue16991]. Esta implementación no permitirá que _map, es decir, _OrderedDict__map se herede. En caso de que tenga que eludir esto y usar el módulo python, puede intentar usar 'py_coll = import_fresh_module ('collections', blocked = ['_ collections']) OrderedDict = py_coll.OrderedDict' – Mikki

5

quiero ni pensar lo lento que esto estará en una lista de tamaño, pero la única manera que he encontrado hasta el momento ...

>>> foo.items()[foo.keys().index('apple') + 1] 
('banana', 3) 

Editar:

El el ejemplo fue un poco artificial; mi colección real está marcada por fechas. Si necesito la entrada después de today; encontró una solución usando 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) 

Un buen bocado.

1

vuelta a trabajar de su código, así que supongo sería un poco mejor:

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) 

Básicamente tener iterador en el lugar correcto ya es suficiente.

Sería bueno comenzar la iteración desde cualquier posición, pero no estoy seguro si-cómo es posible. Necesita un pensamiento

Cuestiones relacionadas