Python字典样式的满射多键→值容器
我现在需要一个Python的容器类,它的功能跟内置的dict
类型差不多。简单来说,我需要一个字典,这个字典可以有多个键,除了一个主要键之外,这些键都指向同一个值。不过,当我遍历这个字典时,它应该只遍历(主要键, 值)
的组合,如果我请求键的列表,它只应该返回主要键。
如果这个功能已经有人实现过,那我就不想再自己重新造轮子了。所以请问有没有现成的模块可以提供这样的容器?如果没有的话,我就打算自己来实现。
3 个回答
0
现在有一个可以使用多个键的字典的Python包。
https://pypi.python.org/pypi/multi_key_dict/1.0.2
从这个链接可以找到更多信息:
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
1
最简单、最容易的办法就是用两个字典,其中一个字典把次要键(secondary keys)映射到主要键(primary key)。如果你出于某种原因需要反向映射(也就是从主要键找到次要键),可以把这个反向映射放在主要字典里。
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])
2
这里有一个简单的实现:
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()
唯一麻烦的地方是,如果一个主键被删除了,它必须在整个字典中进行搜索。
我省略了 copy()
、pop()
、popitem()
和 setdefault()
这些功能。如果你需要用到它们,就得自己实现了。