63

我有od类型OrderedDict。我想访问它最近添加的 (key, value) 对。od.popitem(last = True)会这样做,但也会删除od我不想要的那对。

这样做的好方法是什么?我可以/应该这样做吗:

class MyOrderedDict(OrderedDict):
  def last(self):
    return next(reversed(self))
4

4 回答 4

94

使用next(reversed(od))是访问最近添加的元素的完美方式。该类OrderedDict对字典项和实现使用双向链表__reversed__(),因此此实现使您可以 O(1) 访问所需的元素。是否值得OrderedDict()为这个简单的操作进行子类化可能会受到质疑,但这种方法实际上并没有错。

于 2012-03-28T23:40:48.060 回答
18

来自 timeit 的一点魔法可以在这里提供帮助......

from collections import OrderedDict
class MyOrderedDict1(OrderedDict):
  def last(self):
    k=next(reversed(self))
    return (k,self[k])

class MyOrderedDict2(OrderedDict):
  def last(self):
     out=self.popitem()
     self[out[0]]=out[1]
     return out

class MyOrderedDict3(OrderedDict):
  def last(self):
     k=(list(self.keys()))[-1]
     return (k,self[k])

if __name__ == "__main__":
  from timeit import Timer

  N=100

  d1=MyOrderedDict1()
  for i in range(N): d1[i]=i

  print ("d1",d1.last())

  d2=MyOrderedDict2()
  for i in range(N): d2[i]=i

  print ("d2",d2.last())

  d3=MyOrderedDict3()
  for i in range(N): d3[i]=i

  print("d3",d3.last())



  t=Timer("d1.last()",'from __main__ import d1')
  print ("OrderedDict1",t.timeit())
  t=Timer("d2.last()",'from __main__ import d2')
  print ("OrderedDict2",t.timeit())
  t=Timer("d3.last()",'from __main__ import d3')
  print ("OrderedDict3",t.timeit())

结果是:

d1 (99, 99)
d2 (99, 99)
d3 (99, 99)
OrderedDict1 1.159217119216919
OrderedDict2 3.3667118549346924
OrderedDict3 24.030261993408203

(在 python3.2、Ubuntu Linux 上测试)。

正如@SvenMarnach 所指出的,与我可以烹饪的其他两种方法相比,您描述的方法非常有效。

于 2012-03-29T00:12:21.563 回答
17

上帝,我希望这都是内置功能......

这里有一些可以节省您宝贵时间的东西。在 Python 3.7 中测试。od是你的 OrderedDict。


# Get first key
next(iter(od))

# Get last key
next(reversed(od))

# Get first value
od[next(iter(od))]

# Get last value
od[next(reversed(od))]

# Get first key-value tuple
next(iter(od.items()))

# Get last key-value tuple
next(reversed(od.items()))
于 2019-07-01T13:34:37.880 回答
3

您的想法很好,但是默认迭代器仅在键上,因此您的示例将仅返回最后一个键。你真正想要的是:

class MyOrderedDict(OrderedDict):
    def last(self):
        return list(self.items())[-1]

这给了(key, value)你想要的对,而不仅仅是键。

请注意,在 Python 的 3.x 之前的版本上,OrderedDict.items()返回一个列表,因此您不需要list()调用,但更高版本返回一个字典视图对象,所以您会这样做。

编辑:如评论中所述,更快的操作是:

class MyOrderedDict(OrderedDict):
    def last(self):
        key = next(reversed(self))
        return (key, self[key])

虽然我必须承认我确实在代码中发现了这个丑陋(我从不喜欢获取密钥然后x[key]单独获取值,我更喜欢获取(key, value)元组) - 根据速度的重要性和您的偏好,您可能希望选择前一个选项。

于 2012-03-28T23:46:55.100 回答