use*_*820 -1 python dictionary list-comprehension
这是一个相当简单的查询,而我在这里查看关于字典理解的各种讨论.所以我做了这样的事情:
newlist=[{v:k} for k,v in dicnew.items() if v==value]
>>> newlist
[{2: 'a'}, {2: 'ac'}, {2: 'b'}, {2: 'love'}]
Run Code Online (Sandbox Code Playgroud)
我接下来做的是这样的:
newlist.setdefault(v,[]).append((v,k) for k,v in dicnew.items() if v==value)
>>> newlist
{'go': [<generator object <genexpr> at 0x01E98D50>]}
Run Code Online (Sandbox Code Playgroud)
刚刚发生了什么?这是什么'去'?
您.setdefault()使用以下值调用v:
newlist.setdefault(v,[])
Run Code Online (Sandbox Code Playgroud)
并且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': []}
Run Code Online (Sandbox Code Playgroud)
在setdefault()执行.append()方法之前执行该部分.将v在内部生成表达式中使用名称.append()的方法有什么做的v在使用的名称.setdefault()呼.
在Python 2.7及更早版本中,列表理解变量'泄漏'到父作用域:
>>> [foo for foo in range(3)]
[0, 1, 2]
>>> foo
2
Run Code Online (Sandbox Code Playgroud)
因此,v在前一个循环中设置,并分配给它的最后一个值'go'.
如果您想通过收集每个值的键列表来"反转"字典,请使用:
from collections import defaultdict
keys_for_value = defaultdict(list)
for key, value in original_dict.iteritems():
keys_for_value[value].append(key)
Run Code Online (Sandbox Code Playgroud)
如果你必须坚持单线,使用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)}
Run Code Online (Sandbox Code Playgroud)
这将变得更慢,因为您需要先对字典项进行排序(成本O(n log n))然后循环排序结果(本身为O(n),因此总共O(n)+ O(n log n)),而不是使用defaultdict和for循环的简单O(n)复杂性.
| 归档时间: |
|
| 查看次数: |
131 次 |
| 最近记录: |