2012-09-08 13 views
8

Używam OrderedDict do losowego dostępu listę, ale teraz chcesz rzecz next na liście od tego, który mam:Jak zdobyć "następny" element w OrderedDict?

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

Jak mogę dostać banana używając tylko foo i apple?

+1

'OrderedDict' wydaje się być zbyt proste dla tego produktu. Może działałby okropny jednolinijkowy? 'foo [(klawisze lambda: keys [(keys.index ('pear') + 1)% len (keys)]) (foo.keys())]' – Blender

Odpowiedz

7

Jeśli są OK, z dostępu do tych części realizacji OrderedDict które są celowo utrzymywane private:

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

To więcej niż wgląd, to był wgląd, na który liczyłem. –

+0

W pythonie 3.4 implementacja 'OrderedDict' nieznacznie się zmieniła (patrz [tutaj] (https://hg.python.org/cpython/file/01437956ea67/Lib/collections/__init__.py#l85)). Elementy na połączonej liście są teraz obiektami klasy dummy "_Link". Zamiast dostępu do 'self._OrderedDict__map [key] [1]', należy uzyskać dostęp do 'self._OrderedDict__map [key] .next'. –

+0

W python3.5 rzeczy wydają się mieć jeszcze więcej zmian. Implementacja OrderedDict jest przenoszona do C z Pythona. Sprawdź [https://bugs.python.org/issue16991]. Ta implementacja nie pozwoli na dziedziczenie _map, czyli _OrderedDict__map. Jeśli musisz to obejść i użyć modułu python, możesz spróbować użyć 'py_coll = import_fresh_module ('collections', blocked = ['_ collections']) OrderedDict = py_coll.OrderedDict' – Mikki

5

boję się myśleć jak wolno to będzie na liście rozmiarów, ale tylko sposób mam wymyślić tak daleko ...

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

Edit:

przykład był nieco wymyślny; moja aktualna kolekcja jest kluczowana według dat. Jeśli potrzebuję wpisu po today; znalazłem rozwiązanie przy użyciu funkcji podświetlania ...

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

Całkiem kęs.

1

Reworked z kodu, w ten sposób myślę, że będzie trochę lepiej:

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) 

Zasadniczo posiadające iterator na właściwym miejscu jest już wystarczająco.

Byłoby fajnie rozpocząć iterację z dowolnej pozycji, ale nie jestem pewien, czy - jak to możliwe. Potrzebuje trochę myśli.

Powiązane problemy