在setdefault之后附加到字典中的列表

时间:2016-01-15 16:21:57

标签: python list dictionary append

我有下面的代码,我试图在输入中每次出现一个元素的哈希值时附加1。

def test(Ar):
    hash_table = {}
    for elem in Ar:
        if elem not in hash_table:
            hash_table.setdefault(elem,[]).append(1)
        else:
            hash_table[elem] = hash_table[elem].append(1)
    print(hash_table)

Ar = (1,2,3,4,5,1,2)
test(Ar)

输出:

{1: None, 2: None, 3: [1], 4: [1], 5: [1]}

预期产出:

{1: [1,1], 2: [1,1], 3: [1], 4: [1], 5: [1]}

我很困惑为什么没有人进行追加。请解释发生的事情。

注意:

在键入其他部分时,

hash_table[elem] = hash_table[elem].append(1) # the append() was not suggested at all by the IDE. I forcibly put it, hoping things will work.

2 个答案:

答案 0 :(得分:5)

list.append是就地操作。所以它只是修改了列表对象并且没有返回任何内容。这就是为什么默认情况下Nonelist.append返回,并且您正在存储与此行中的键相对应的内容

hash_table[elem] = hash_table[elem].append(1)

在您的情况下,您根本不需要if条件。

def test(Ar):
    hash_table = {}
    for elem in Ar:
        hash_table.setdefault(elem, []).append(1)
    print(hash_table)

因为,setdefault首先会在其中查找密钥elem并找到一些内容,然后它会返回与之对应的值。如果它没有,那么它将创建键elem并使用传递给它的第二个参数作为值,然后返回值。

您可以使用collections.defaultdict,而不是使用此

from collections import defaultdict
def test(Ar):
    hash_table = defaultdict(list)
    for elem in Ar:
        hash_table[elem].append(1)
    print(hash_table)

这与setdefault版本

几乎完全相同

看起来你正试图找到元素的频率。在这种情况下,您只需使用collections.Counter

即可
from collections import Counter
Ar = (1, 2, 3, 4, 5, 1, 2)
print Counter(Ar)
# Counter({1: 2, 2: 2, 3: 1, 4: 1, 5: 1})

这将给出迭代传递中每个元素出现的次数。

答案 1 :(得分:1)

错误就在这一行:

hash_table[elem] = hash_table[elem].append(1)

list.append(x)返回您None分配的hash_table[elem]

else部分是不必要的,但仍然是为了获得正确的结果,请删除else部分中的作业。

请注意,None仅适用于出现两次的元素。如果任何元素存在三次,那么您就会收到错误。