2016-06-28 98 views
1

这是我的函数:Python中的多路频率函数?

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

在给定的嵌套级别的每个字典都是相同的字典。 – user2357112

回答

2

的问题是,在d字典所有嵌套类型的字典是同一个对象。使用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 typesHow do I pass a variable by reference?

祝你好运!

+0

@LMc它会回答你的问题吗? –

0

您已经以某种方式初始化了d的值到同一字典。我无法自信地解决这个问题,因为我没有在这里安装Python3(脸红)。不过,我认为问题在于中间线的值:我认为它将相同的默认字典插入到每个值中。尝试创建一个新的空字典为每次通过此迭代。

0

显然,内部字典中引用相同的对象和一切都得到simultenously更新,如从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为每个密钥创建多个副本。


但为什么经过上getitem使用reduce的所有麻烦。你的代码部分很难调试。

您可以使用您一个Counter对象实现同样的事情拉链项目:

from collections import Counter 

var = ['a','b','b','c'],['one','two','two','two'] 

c = Counter(zip(*var)) 
d = {k[0]: {j: v if j in k else 0 for j in set(var[1])} for k,v in c.items()} 
print(d) 
# {'b': {'two': 2, 'one': 0}, 'c': {'two': 1, 'one': 0}, 'a': {'two': 0, 'one': 1}} 
+0

'var'可能有一个或多个元素。在这里,我使用了两个,但它可能会更多或更少。 – LMc

+0

通过在dict理解中创建更深的嵌套,可以扩展代码。你可以通过将它重构为一个循环,使其认识到'var'中的元素数量,使其成为一个动态。 –