私はod
タイプを持っていOrderedDict
ます。最近追加された(キー、値)ペアにアクセスしたい。それをしますが、私が望まないod.popitem(last = True)
ペアも削除します。od
それを行うための良い方法は何ですか?私はこれを行うことができます/すべきですか:
class MyOrderedDict(OrderedDict):
def last(self):
return next(reversed(self))
私はod
タイプを持っていOrderedDict
ます。最近追加された(キー、値)ペアにアクセスしたい。それをしますが、私が望まないod.popitem(last = True)
ペアも削除します。od
それを行うための良い方法は何ですか?私はこれを行うことができます/すべきですか:
class MyOrderedDict(OrderedDict):
def last(self):
return next(reversed(self))
使用next(reversed(od))
は、最近追加された要素にアクセスするための完璧な方法です。このクラスOrderedDict
は、ディクショナリ項目に二重リンクリストを使用して実装する__reversed__()
ため、この実装により、目的の要素へのO(1)アクセスが可能になります。この単純な操作でサブクラス化する価値があるかどうかはOrderedDict()
疑問視されるかもしれませんが、このアプローチには実際には何の問題もありません。
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つの方法と比較して非常に効率的です。
神様、これがすべて組み込みの機能だったらいいのにと思います...
これがあなたの貴重な時間を節約するための何かです。Python3.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()))
あなたの考えは問題ありませんが、デフォルトのイテレータはキー上にのみあるため、例では最後のキーのみが返されます。あなたが実際に欲しいのは:
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)
タプルを取得することをお勧めします)-速度の重要性と好みに応じて、以前のオプション。