3

我想制作一个每个值有多个键的二维字典。我不想使元组成为键。而是制作许多返回相同值的键。

我知道如何使用 defaultdict 制作二维字典:

from collections import defaultdict
a_dict = defaultdict(dict)

a_dict['canned_food']['spam'] = 'delicious'

我可以使用使元组成为键

a_dict['food','canned_food']['spam'] = 'delicious'

但这不允许我做类似的事情

print a_dict['canned_food']['spam']

因为 'canned_food' 不是键,所以元组 ['food','canned_food'] 是键。

我了解到,我可以简单地将许多独立设置为相同的值,例如:

a_dict['food']['spam'] = 'delicious'
a_dict['canned_food']['spam'] = 'delicious'

但这会因大量键而变得混乱。在字典的第一维中,每个值我需要约 25 个键。有没有办法编写字典,以便元组中的任何键都可以工作?

我之前问过这个问题, 但不清楚我想要什么,所以我重新发布。预先感谢您的任何帮助。

4

2 回答 2

8

这是一个可能的解决方案:

from collections import Iterable

class AliasDefaultDict():
    def __init__(self, default_factory, initial=[]):
        self.aliases = {}
        self.data = {}
        self.factory = default_factory
        for aliases, value in initial:
            self[aliases] = value

    @staticmethod
    def distinguish_keys(key):
        if isinstance(key, Iterable) and not isinstance(key, str):
            return set(key)
        else:
            return {key}

    def __getitem__(self, key):
        keys = self.distinguish_keys(key)
        if keys & self.aliases.keys():
            return self.data[self.aliases[keys.pop()]]
        else:
            value = self.factory()
            self[keys] = value
            return value

    def __setitem__(self, key, value):
        keys = self.distinguish_keys(key)
        if keys & self.aliases.keys():
            self.data[self.aliases[keys.pop()]] = value
        else:
            new_key = object()
            self.data[new_key] = value
            for key in keys:
                self.aliases[key] = new_key
            return value

    def __repr__(self):
        representation = defaultdict(list)
        for alias, value in self.aliases.items():
            representation[value].append(alias)
        return "AliasDefaultDict({}, {})".format(repr(self.factory), repr([(aliases, self.data[value]) for value, aliases in representation.items()]))

可以这样使用:

>>> a_dict = AliasDefaultDict(dict)
>>> a_dict['food', 'canned_food']['spam'] = 'delicious'
>>> a_dict['food']
{'spam': 'delicious'}
>>> a_dict['canned_food']
{'spam': 'delicious'}
>> a_dict
AliasDefaultDict(<class 'dict'>, [(['food', 'canned_food'], {'spam': 'delicious'})])

请注意,有些边缘情况具有未定义的行为 - 例如对多个别名使用相同的键。我觉得这使得这种数据类型对于一般用途来说非常糟糕,我建议你最好改变你的程序而不需要这种过于复杂的结构。

str另请注意,此解决方案适用于 3.x,在 2.x下,您需要换掉basestringself.aliases.keys()self.aliases.viewkeys()

于 2012-11-12T01:03:58.790 回答
2

这有帮助吗?

class MultiDict(dict):
    # define __setitem__ to set multiple keys if the key is iterable
    def __setitem__(self, key, value):
        try:
            # attempt to iterate though items in the key
            for val in key:
                dict.__setitem__(self, val, value)
        except:
            # not iterable (or some other error, but just a demo)
            # just set that key
            dict.__setitem__(self, key, value)



x = MultiDict()

x["a"]=10
x["b","c"] = 20

print x

输出是

{'a': 10, 'c': 20, 'b': 20}
于 2012-11-12T00:46:00.653 回答