我可以使用同名密钥的字典吗?

时间:2011-07-25 08:44:33

标签: python dictionary key

我需要一个字典,它可能对某些键具有相同的名称,并在这种情况下引用键时返回值列表。

例如

print mydict['key']
[1,2,3,4,5,6]

5 个答案:

答案 0 :(得分:14)

为了保持一致性,您应该使用字典映射键来列出(或设置)值,其中一些可以为空。对此有一个很好的习语:

from collections import defaultdict
d = defaultdict(set)

d["key"].add(...)

(A defaultdict就像一个普通的字典,但是如果缺少一个键,它会在你实例化它时调用你传入的参数并使用结果作为默认值。所以这会自动创建一个空如果您要求一个尚未存在的密钥,则设置一组值。)


如果您需要对象看起来更像字典(即通过d["key"] = ...设置值),您可以执行以下操作。 但是这可能是一个坏主意,因为它违反了普通的Python语法,并且很可能会在以后再次出现。特别是如果其他人必须维护您的代码。

class Multidict(defaultdict):
    def __init__(self):
        super(Multidict, self).__init__(set)

    def __setitem__(self, key, value):
        self[key].add(value)

我没有测试过这个。

答案 1 :(得分:11)

您还可以尝试paste.util.multidict.MultiDict

$ easy_install Paste

然后:

from paste.util.multidict import MultiDict
d = MultiDict()
d.add('a', 1)
d.add('a', 2)
d.add('b', 3)
d.mixed()
>>> {'a': [1, 2], 'b': 3}
d.getall('a')
>>> [1, 2]
d.getall('b')
>>> [3]

Pylons等Web框架正在使用此库来处理HTTP查询字符串/发布数据,这些数据可以使用同名密钥。

答案 2 :(得分:6)

您可以使用:

myDict = {'key': []}

然后在运行时:

if newKey in myDict:
    myDict[newKey].append(value)
else:
    myDict[newKey] = [value]

根据@ Ben的评论编辑:

myDict = {}
myDict.setdefault(newKey, []).append(value)

答案 3 :(得分:1)

def toMultiDict(items):
    def insertMulti(d, kv):
        k, v = kv
        d.setdefault(k, []).append(v)
        return d
    return reduce(insertMulti, [{}] + items)

应该从键创建一个dict到值列表:

In [28]: toMultiDict(zip([1,2,1], [4,5,6]))
Out[28]: {1: [4, 6], 2: [5]}

我无法将insertMulti放入lambda中,因为lambda需要再次返回dict。

答案 4 :(得分:1)

这是使用集合库

中的defaultdict对象的理想位置
from collections import defaultdict

mydict = defaultdict(set)
mydict['key'] += set([1,2,3,4])
mydict['key'] += set([4,5,6])

print(mydict['key'])

返回[1,2,3,4,5,6]

如果引用的键未被隐式分配,则返回空集。

print(mydict['bad_key'])

返回[]

在标准库的dict上使用 setdefault ,在分配值时需要对语法进行重大更改,并且可能会变得相当混乱。我从来没有使用过Multidict,但它看起来也像是在分配方式上发生了重大变化。使用此方法,您只需假设字典中可能已存在与此键关联的值,并在分配键值时使用“+ =”运算符稍微修改赋值运算符。

仅供参考 - 我非常喜欢使用NoneType作为默认值,导致无效密钥的任何访问都返回None。这在大多数情况下都适用,包括迭代和json转储,但是对于您的特定需要,默认值应该是 set 类型,除非您要启用密钥中存储的重复值。然后使用列表。事实上,只要你有一个同质字典,默认应该是那种类型。

mydict = defaultdict(lambda: None)