2017-11-02 6 views
0

ジェネレータを使用しているときに、渡されたディクショナリを変更しても、ジェネレータは古いデータ構造で結果を返します。 どうすれば修正できますか?発電機を使用しているときに辞書を最新の状態に保つにはどうすればいいですか?

def min_key_order(adict:dict): 
    for key, value in sorted(adict.items()): 
     yield (key, value) 

d = {1:'a', 2:'x', 4:'m', 8:'d', 16:'f'} 
i = min_key_order(d) 
print(next(i)) 
d.pop(2) 
print(next(i)) 

そして、それは私に(1,'a')を与え、(2,'x')、でも私は、辞書からポップ・キー2を持っています。

+2

変更した辞書を反復処理することはできません。それはサポートされていない動作です。 –

+1

しかし、 'sorted()'関数は**新しいリストを生成します**;そのリストは元のdicitonaryの変更に従うように更新されることはありません。 –

+0

これらのどちらもジェネレータと関係がありません。 'd.pop()'を 'for'ループの中に' sorted(d) 'を置いて同じ動作をします。 –

答えて

2

あなたのジェネレータは辞書を反復していません。 sorted()が返されることを新しいリストオブジェクトを反復処理されています。辞書から項目を削除する

>>> d = {1:'a', 2:'x', 4:'m', 8:'d', 16:'f'} 
>>> l = sorted(d.items()) 
>>> d 
{1: 'a', 2: 'x', 4: 'm', 8: 'd', 16: 'f'} 
>>> l 
[(1, 'a'), (2, 'x'), (4, 'm'), (8, 'd'), (16, 'f')] 
>>> d.pop(2) 
'x' 
>>> l 
[(1, 'a'), (2, 'x'), (4, 'm'), (8, 'd'), (16, 'f')] 

は、新しいリストを更新することはできません。その構造は辞書のライブビューではありません。仕事にそのために

、あなたは再ソート辞書にそれぞれすべての反復を持っている、と繰り返し位置を追跡したい:

def sorted_view(d): 
    pos = 0 
    while pos < len(d): 
     yield sorted(d.items())[pos] 
     pos += 1 

これは非常に非効率的です。ソーティングは比較的高価な操作です。

Aより効率的な方法は、ソート順でだけのキーを格納するだろうし、キーはまだ利用できテストの場合:あなたを追加した場合

def min_key_order(adict:dict): 
    for key in sorted(adict): 
     if key in adict: 
      yield (key, adict[key]) 

しかしこれは検出されません。より多くのキー。

関連する問題