这是我的功能:
def freq(*var):
from functools import reduce
from operator import getitem
for c,i in enumerate(reversed(var)):
d={k:0 for k in set(i)} if c==0 else {k:d for k in set(i)}
for row in zip(*var):
*k,last_k=row
reduce(getitem,k,d)[last_k]+=1
return d
var
参数看起来像(['a','b','b','c'],['one','two','two','two'])
我正在尝试返回一个包含频率计数的嵌套字典。因此结果d
应如下所示:
{'a':{'one':1, 'two':0}, 'b':{'one':0, 'two':2}, 'c':{'one':0, 'two':1}}
但是我的函数返回了,这是错误的:
{'a': {'one': 1, 'two': 3}, 'b': {'one': 1, 'two': 3}, 'c': {'one': 1, 'two': 3}}
知道为什么吗?
答案 0 :(得分:2)
问题是d
dict中的所有嵌套dicts都是同一个对象。使用dict.copy()方法修复问题,因此更改行:
d={k:0 for k in set(i)} if c==0 else {k:d for k in set(i)}
到
d={k:0 for k in set(i)} if c==0 else {k:d.copy() for k in set(i)}
可以解决您的问题。详情请见Immutable vs Mutable types和How do I pass a variable by reference?
祝你好运!
答案 1 :(得分:0)
您已经以某种方式将 d 的值初始化为同一个字典。我无法自信地解决这个问题,因为我没有安装Python3(腮红)。但是,我认为问题在于中间行的 k:d 值:我认为它会将相同的默认字典插入到每个值中。尝试为此次迭代中的每次传递创建 new 空字典。
答案 2 :(得分:0)
显然,内部dict引用同一个对象,所有内容都会同时更新,如final Callable<String> lambdaGetValString = () -> String.valueOf(this.val);
循环所示:
enumerate
循环的第二次迭代中使用的内部字典for c,i in enumerate(reversed(var)):
d={k:0 for k in set(i)} if c==0 else {k:d for k in set(i)}
# ^
是同一个对象。您可以使用d
代替d.copy()
为每个密钥创建多个副本。
但为什么要在d
上使用reduce
时遇到麻烦。你的代码部分很难调试。
您可以在压缩项目上使用getitem
对象来实现相同的目标:
Counter