web-dev-qa-db-ja.com

OrderedDictの最後の要素

タイプodOrderedDictがあります。最近追加された(キー、値)ペアにアクセスしたい。 od.popitem(last = True)はそれを行いますが、odからペアを削除しますが、これは不要です。

それを行うための良い方法は何ですか?私はこれを行うことができますか?

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

next(reversed(od))を使用すると、最近追加された要素にアクセスできます。クラスOrderedDictは、辞書項目に二重にリンクされたリストを使用し、 __reversed__() を実装しているため、この実装はO(1)アクセスを提供します目的の要素に。この単純な操作でOrderedDict()をサブクラス化する価値があるかどうかは疑問ですが、このアプローチには実際には何も問題はありません。

62
Sven Marnach

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で指摘されているように、あなたが説明した方法は、私が調理できる他の2つの方法に比べて非常に効率的です。

15
mgilson

神様、これがすべて組み込みの機能だったらいいのに...

これは貴重な時間を節約するためのものです。 Python= 3.7でテストされています。odはOrderedDictです。


# Get first key
next(iter(od.keys()))

# Get last key
next(reversed(od.keys()))

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

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

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

# Get last key-value Tuple
next(reversed(od.items()))
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)_タプルを取得することを好みます)。そしてあなたの好み、あなたは前者のオプションを選ぶことを望むかもしれません。

2
Gareth Latty