Question

Je suis actuellement dans la nécessité d'une classe de conteneur Python avec des fonctionnalités similaires comme le type builtin dict. Fondamentalement, ce que j'ai besoin est un dictionnaire, où un nombre arbitraire de clés à côté d'une clé primaire, quelle carte à la valeur même. Cependant lorsque vous parcourez, il devrait itérer que sur les paires de (primary_key, value) et que la clé primaire si la liste des clés est demandée.

Si cela a déjà été mis en œuvre, je préfère ne pas réinventer la roue. Donc, il y a déjà un module fournissant un tel conteneur? Sinon, je vais la mettre en œuvre moi-même.

Était-ce utile?

La solution

Voici une mise en œuvre rapide:

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

Le seul peu en désordre est qu'il doit rechercher l'ensemble dict au cas où une clé primaire est supprimé.

J'omis copy(), pop(), popitem() et setdefault(). Si vous avez besoin, vous devrez les mettre en œuvre vous.

Autres conseils

La solution la plus simple et la plus simple serait d'utiliser deux dictionnaires, dont une des cartes clés secondaires à une clé primaire. Si pour une raison quelconque, vous avez besoin d'une cartographie inverse, qui pourrait être inclus dans le dictionnaire principal.

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

Il y a maintenant un paquet multiple clé python dictionnaire.
https://pypi.python.org/pypi/multi_key_dict/1.0.2

À partir du lien:

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, e.g. for example above:
k['kilo'] = 'kilo'
print k[1000] # will now print 'kilo' as value was updated
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top