2012-09-08 31 views
8

Tôi đang sử dụng một OrderedDict để truy cập ngẫu nhiên một danh sách, nhưng bây giờ muốn next mục trong danh sách từ một trong đó tôi có:Cách lấy mục "tiếp theo" trong OrderedDict?

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

Làm thế nào để tôi có được chuối chỉ sử dụng fooapple?

+1

'OrderedDict' có vẻ là quá đơn giản cho việc này. Có lẽ một lớp lót khủng khiếp sẽ hoạt động? 'foo [(phím lambda: phím [(keys.index ('lê') + 1)% len (phím)]) (foo.keys())]' – Blender

Trả lời

7

Nếu bạn là OK với việc tiếp cận những phần của việc thực hiện OrderedDict được cố ý giữ kín:

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

Hơn OK, đó là cái nhìn sâu sắc mà tôi đã hy vọng. –

+0

Trong python 3.4 việc thực hiện 'OrderedDict' hơi thay đổi (xem [ở đây] (https://hg.python.org/cpython/file/01437956ea67/Lib/collections/__init__.py#l85)). Các phần tử trên danh sách liên kết bây giờ là các đối tượng của một lớp giả '_Link'. Thay vì truy cập 'self._OrderedDict__map [key] [1]', bạn nên truy cập 'self._OrderedDict__map [key] .next'. –

+0

Trong python3.5 mọi thứ dường như thậm chí còn thay đổi nhiều hơn. Việc thực hiện OrderedDict được chuyển đến C từ python. Kiểm tra [https://bugs.python.org/issue16991]. Triển khai này sẽ không cho phép _map tức là _OrderedDict__map được kế thừa. Trong trường hợp bạn phải phá vỡ điều này và sử dụng mô-đun python, có thể thử sử dụng 'py_coll = import_fresh_module ('collections', blocked = ['_ collections']) OrderedDict = py_coll.OrderedDict' – Mikki

5

Tôi rùng mình khi nghĩ đến việc chậm này sẽ được trên một danh sách các kích thước, nhưng chỉ cách tôi đã đi lên với cho đến nay ...

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

Edit:

Các ví dụ hơi hơi giả tạo; bộ sưu tập thực tế của tôi được khóa theo ngày. Nếu tôi cần mục nhập sau today; tìm thấy một giải pháp bằng cách sử dụng 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) 

Khá một chút.

1

Làm lại từ mã của bạn, cách này tôi đoán sẽ là tốt hơn một chút:

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) 

Về cơ bản có iterator ở đúng nơi là đã đủ.

Sẽ rất thú vị để bắt đầu lặp lại từ bất kỳ vị trí nào, nhưng không chắc chắn nếu có thể. Cần một số suy nghĩ.

Các vấn đề liên quan