如何在Python字典中为一个键添加多个值

7

我正在尝试从name_num字典的值创建一个新的字典,其中列表的长度是新键,而name_num字典的键和值是值。因此:

name_num = {"Bill": [1,2,3,4], "Bob":[3,4,2], "Mary": [5, 1], "Jim":[6,17,4], "Kim": [21,54,35]}

我想创建以下字典:
new_dict = {4:{"Bill": [1,2,3,4]}, 3:{"Bob":[3,4,2], "Jim":[6,17,4], "Kim": [21,54,35]}, 2:{"Mary": [5, 1]}}

我尝试了许多变化,但这段代码让我离目标最近:
for mykey in name_num:
    new_dict[len(name_num[mykey])] = {mykey: name_num[mykey]}

输出:

new_dict = {4:{"Bill": [1,2,3,4]}, 3:{"Jim":[6,17,4]}, 2:{"Mary": [5, 1]}}

我知道需要以某种方式循环遍历代码,这样才能将其他值添加到键3。

3个回答

21

这是使用defaultdict的一个很好的例子:

from collections import defaultdict
name_num = {
    'Bill': [1, 2, 3, 4],
    'Bob': [3, 4, 2],
    'Mary': [5, 1],
    'Jim': [6, 17, 4],
    'Kim': [21, 54, 35],
}

new_dict = defaultdict(dict)
for name, nums in name_num.items():
    new_dict[len(nums)][name] = nums

print(dict(new_dict))

输出:

{
    2: {'Mary': [5, 1]},
    3: {'Bob': [3, 4, 2], 'Jim': [6, 17, 4], 'Kim': [21, 54, 35]},
    4: {'Bill': [1, 2, 3, 4]}
}

Karin,干得好。我对defaultdict不太熟悉。我想一旦你创建了一个默认字典,只需要用数据填充它就可以了。 - Oedipus
是的 - 默认字典基本上允许您为字典键设置默认值,如果您尝试访问该键并且它尚不存在,则会使用默认值。这非常方便 :) - Karin
我没想到 defaultdict 会因为被访问而保留它的值。 - Bergi
@Bergi 这将与可变值不一致。例如,如果您有:d = defaultdict(list); value = d[non_existent_key]; value.append(1),则期望在字典中有键值对non_existent_key: [1],但是如果defaultdict在访问时不保留创建的默认值,则始终会得到[]defaultdict的属性是,当您尝试以任何方式访问不存在的键时,该键会添加默认值。唯一不触发键创建的检查是像key in the_dict这样的检查。 - Bakuriu
@Bakuriu:感谢您的解释。但实际上,我已经预料到了变异不起作用,这就是为什么我进行了评论。在其他语言中,默认值仅用于获取,而不会隐式创建键。 - Bergi
2
@Bergi 基本上,defaultdict 的想法是在人们使用普通 dict 类的 setdefault 方法时开发出来的。你可以像这样使用它:d.setdefault(key, default_value)。这就像一个 get,但如果键不存在,它会添加它并分配 default_value 的值。问题是,函数调用总是创建默认值,因此可能会相当慢。defaultdict 是一个优化的字典,其中每个 get 调用基本上都是一个 setdefault 调用,但它可以避免在键存在时创建默认值,以实现最大的简洁和速度。 - Bakuriu

5
字典、关联数组或映射(有许多名称,基本上具有相同的功能)的属性是键是唯一的。

如果长度相同,则您希望拥有的整数键不是唯一的,这就是为什么您的代码无法正常工作的原因。为现有键添加新值意味着替换旧值。

您必须将键值对添加到现有值字典中。

for mykey in name_num:
    length = len(name_num[mykey])
    if length in new_dict: # key already present in new dictionary
        new_dict[length][mykey] = name_num[mykey]
    else:
        new_dict[length] = {mykey: name_num[mykey]}

应该可以解决问题。


1
谢谢Jezor。我是Python的新手。这澄清了如何向字典添加数据的许多困惑。 - Oedipus

4

这只是与其他方式的替代。您可以按照长度排序并使用itertools.groupby

>>> result = {}
>>> f = lambda t: len(t[1])
>>> for length, groups in itertools.groupby(sorted(name_num.items(), key=f), key=f):
...     result[length] = dict((k, v) for k, v in groups)
>>> print result
{
    2: {'Mary': [5, 1]},
    3: {'Bob': [3, 4, 2], 'Jim': [6, 17, 4], 'Kim': [21, 54, 35]},
    4: {'Bill': [1, 2, 3, 4]}
}

如果每个内部列表的长度都不同,那么在最坏情况下,这将执行O(n^2),与上面发布的其他解决方案相比效率相当低。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接