How to get the “next” item in an OrderedDict?

后端 未结 4 874
野的像风
野的像风 2021-02-08 01:44

I\'m using an OrderedDict to random access a list, but now want the next item in the list from the one that I have:

foo = OrderedDict([(\'apple\', 4         


        
相关标签:
4条回答
  • 2021-02-08 02:24

    Python 3.X

    dict.items would return an iterable dict view object rather than a list. We need to wrap the call onto a list in order to make the indexing possible:

    >>> 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
    
    0 讨论(0)
  • 2021-02-08 02:28

    I shudder to think how slow this will be on a list of size, but the only way I've come up with so far...

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

    Edit:

    The example was slightly contrived; my actual collection is keyed by dates. If I need the entry after today; found a solution using 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)
    

    Quite a mouthful.

    0 讨论(0)
  • 2021-02-08 02:42

    Reworked from your code, this way I guess would be a little better:

    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)
    

    Basically having iterator at the right place is already enough.

    Would be cool to start iteration from any position, but not sure if-how possible. Needs some thought.

    0 讨论(0)
  • 2021-02-08 02:47

    If you are OK with accessing those parts of the OrderedDict implementation that are intentionally kept 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'
    
    0 讨论(0)
提交回复
热议问题