2012-09-08 7 views
8

私はランダムアクセスにリストをOrderedDictを使用して、今私が持っているものから一覧でnextアイテムをしたいんだ:OrderedDictの「次の」項目を取得する方法は?

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

私はちょうどfooappleを使用してバナナを取得するにはどうすればよいですか?

+1

'OrderedDict'は、このために単純すぎるように思われます。恐ろしいワンライナーがうまくいくかもしれませんか? (foo.keys())] ' – Blender

答えて

7

あなたが意図的に非公開にされOrderedDict実装の部分にアクセスするとOKしている場合:

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

OK以上のことは、私が望んでいた洞察です。 –

+0

Python 3.4では 'OrderedDict'の実装が少し変更されました([here](https://hg.python.org/cpython/file/01437956ea67/Lib/collections/__init__.py#l85)参照)。リンクされたリストの要素は、ダミークラス '_Link'のオブジェクトになりました。 'self._OrderedDict__map [key] [1]'にアクセスするのではなく、 'self._OrderedDict__map [key] .next'にアクセスする必要があります。 –

+0

python3.5では、さらに変化しているようです。 OrderedDictの実装はPythonからCに移されます。 [https://bugs.python.org/issue16991]を確認してください。この実装では、_mapすなわち_OrderedDict__mapを継承することはできません。あなたがこれを回避してpythonモジュールを使用する必要がある場合は、 'py_coll = import_fresh_module( 'collections'、blocked = ['_ collections'])を試すことができます。 OrderedDict = py_coll.OrderedDict' – Mikki

5

私は、これはサイズのリストになりますどのように遅いと思うとぞっとが、私は今のところ...

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

編集を作ってみたのみ方法:

例はわずかに考案された。私の実際のコレクションは日付でキー付けされています。 todayの後に入力が必要な場合は、ドロップを使用して解決策を見つけました。

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

かなり口が開いています。あなたのコードから作り直し

1

は、私は少し良いだろうと思い、このよう:

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) 

基本的には、適切な場所に反復子を持つはすでに十分です。

任意の位置から反復を開始するのは楽ですが、if-howが可能かどうかはわかりません。いくつかの考えが必要です。

関連する問題