Python dict as a surjective plural key -> value container

I currently need a Python class container with similar functionality, such as the built-in dict type. Basically I need a dictionary where an arbitrary number of keys are next to the primary key, which are mapped to the same value. However, when navigating through it, it should iterate over only the pairs (primary_key, value) and only the primary key if a list of keys is requested.

If this is already implemented, I would prefer not to reinvent the wheel. So is there already a module that provides such a container? If not, I'm going to implement it myself.

+4
source share
3 answers

Here is a quick implementation:

 class MultipleKeyDict(dict): __slots__ = ["_primary_keys"] def __init__(self, arg=None, **kwargs): self._primary_keys = {} self.update(arg, **kwargs) def __setitem__(self, key, value): super(MultipleKeyDict, self).__setitem__(key, value) self._primary_keys.setdefault(value, key) def __delitem__(self, key): value = self[key] super(MultipleKeyDict, self).__delitem__(key) if self._primary_keys[value] == key: del self._primary_keys[value] for k, v in super(MultipleKeyDict, self).iteritems(): if v == value: self._primary_keys[value] = k break def __iter__(self): return self.iterkeys() def update(self, arg=None, **kwargs): if arg is not None: if isinstance(arg, collections.Mapping): for k in arg: self[k] = arg[k] else: for k, v in arg: self[k] = v for k in kwargs: self[k] = kwargs[k] def clear(self): super(MultipleKeyDict, self).clear() self._primary_keys.clear() def iteritems(self): for v, k in self._primary_keys.iteritems(): yield k, v def items(self): return list(self.iteritems()) def itervalues(self): return self._primary_keys.iterkeys() def values(self): return self._primary_keys.keys() def iterkeys(self): return self._primary_keys.itervalues() def keys(self): return self._primary_keys.values() 

The only messy bit is that it should look for the entire dict if the primary key is deleted.

I missed copy() , pop() , popitem() and setdefault() . If you need them, you will have to implement them yourself.

+2
source

The simplest and easiest solution would be to use two dictionaries, one of which displays secondary keys for the primary key. If for some reason you need a reverse mapping, which can be included in the main dictionary.

 sec = {'one': 'blue', 'two': 'red', 'three': 'blue', # seconary keys 'blue': 'blue', 'red': 'red'} # include identity mapping for primaries dict = {'blue': ('doll', '$9.43', ('one', 'three')), 'red': ('truck', '$14.99', ('two',)) } record = dict[sec['two']] print('Toy=', record[0], 'Price=', record[1]) 
+1
source

There is currently a python package with several key dictionaries.
https://pypi.python.org/pypi/multi_key_dict/1.0.2

From the link:

  from multi_key_dict import multi_key_dict

 k = multi_key_dict ()
 k [1000, 'kilo', 'k'] = 'kilo (x1000)'

 print k [1000] # will print 'kilo (x1000)'
 print k ['k'] # will also print 'kilo (x1000)'

 # the same way objects can be updated, deleted:
 # and if an object is updated using one key, the new value will
 # be accessible using any other key, eg for example above:
 k ['kilo'] = 'kilo'
 print k [1000] # will now print 'kilo' as value was updated
0
source

Source: https://habr.com/ru/post/1383478/


All Articles