-1

ここで辞書の理解に関するさまざまな議論をチェックしていたとき、これはかなり単純なクエリです。だから私はこのようなことをしました:

newlist=[{v:k} for k,v in dicnew.items() if v==value]
>>> newlist
[{2: 'a'}, {2: 'ac'}, {2: 'b'}, {2: 'love'}]

私が次にしたことは次のようなものです:

newlist.setdefault(v,[]).append((v,k) for k,v in dicnew.items() if v==value)
>>> newlist
{'go': [<generator object <genexpr> at 0x01E98D50>]}

今何があったの?この「行く」は何ですか?

4

1 に答える 1

5

の値で呼び出し.setdefault()ましv:

newlist.setdefault(v,[])

vがすでに定義されていて、 に設定されている必要があります'go'。このコードを新しいインタープリターで実行するか、del v最初に実行すると、Python はNameError代わりに例外を発生させます。

>>> newlist = {}
>>> newlist.setdefault(v,[]).append((v,k) for k,v in dicnew.items() if v==value)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'v' is not defined
>>> v = 'go'
>>> newlist.setdefault(v, [])
[]
>>> newlist
{'go': []}

このsetdefault()部分は、.append()メソッドが実行される前に実行されます。メソッドv内のジェネレーター式で使用される名前は、呼び出しで使用される名前とは関係ありません。.append()v.setdefault()

Python 2.7 以前では、親スコープに「リーク」する内包変数を一覧表示します。

>>> [foo for foo in range(3)]
[0, 1, 2]
>>> foo
2

そのため、vは前のループで設定され、最後に割り当てられた値は'go'です。

各値のキーのリストを収集して辞書を「反転」したい場合は、次を使用します。

from collections import defaultdict

keys_for_value = defaultdict(list)
for key, value in original_dict.iteritems():
    keys_for_value[value].append(key)

ワンライナーを主張する必要がある場合は、次を使用itertools.groupbyして並べ替えます。

from itertools import groupby
from operator import itemgetter

v = itemgetter(1)
keys_for_value = {value: [k for k, v in items] for value, items in groupby(sorted(original_dict.iteritems(), key=v, key=v)}

ソートされた結果 (それ自体 O(n)) をループする前に、最初に辞書項目をソートする必要があるため (コスト O(n log n))、これは遅くなります。つまり、合計 O(n) + O(n log n)) を使用する単純な O(n) の複雑さdefaultdictforループとは対照的です。

于 2013-05-02T17:51:48.143 に答える