2d dictionary with many keys that will return the same value

前端 未结 2 1296
臣服心动
臣服心动 2021-01-03 10:17

I want to make a 2d dictionary with multiple keys per value. I do not want to make a tuple a key. But rather make many keys that will return the same value.

I know ho

相关标签:
2条回答
  • 2021-01-03 10:38

    Here is a possible solution:

    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()]))
    

    Which can be used like so:

    >>> 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'})])
    

    Note there are some edge cases with undefined behavior - such as using the same key for multiple aliases. I feel this makes this data type pretty awful for general use, and I'd suggest that you may be better off changing your program not to need this kind of overly convoluted structure instead.

    Also note this solution is for 3.x, under 2.x, you will want to swap out str for basestring, and self.aliases.keys() for self.aliases.viewkeys().

    0 讨论(0)
  • 2021-01-03 10:38

    Does this help at all?

    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
    

    The output is

    {'a': 10, 'c': 20, 'b': 20}
    
    0 讨论(0)
提交回复
热议问题