3

値ごとに複数のキーを持つ2D辞書を作成したいと思います。タプルをキーにしたくありません。ただし、同じ値を返すキーを多数作成してください。

defaultdictを使用して2D辞書を作成する方法を知っています。

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 に答える