Multiples-keys字典,其中键顺序无关紧要

时间:2017-10-08 15:54:10

标签: python dictionary

我正在尝试创建一个包含两个字符串作为键的字典,我希望键可以按任何顺序排列。

myDict[('A', 'B')] = 'something'
myDict[('B', 'A')] = 'something else'
print(myDict[('A', 'B')])

我希望这段代码能够打印“别的东西”。不幸的是,似乎订单与元组有关。什么是最好的数据结构用作关键?

3 个答案:

答案 0 :(得分:19)

使用frozenset

而不是订购的tuple,您可以使用<{1>} 无序,而 hashable 为{{ 1}}是不可变的

frozenset

将打印:

frozenset

不幸的是,这种简单性带来了一个缺点,因为myDict = {} myDict[frozenset(('A', 'B'))] = 'something' myDict[frozenset(('B', 'A'))] = 'something else' print(myDict[frozenset(('A', 'B'))]) 基本上是一个“冻结”的集合。 something else 中没有重复值,例如

frozenset

如果修改值不会打扰您,请随意使用frozenset

但如果你100%确定你不想要上面提到的内容发生,那么有两个替代品:

第一个方法是使用frozenset((1, 2)) == frozenset((1,2,2,1,1)) ,并再次使用frozenset使其成为Counter :( 注意:元组中的所有内容都必须是 hashable

hashable

第二个方法是使用内置函数frozenset,并使其成为from collections import Counter myDict = {} myDict[frozenset(Counter(('A', 'B')).items())] = 'something' myDict[frozenset(Counter(('B', 'A')).items())] = 'something else' print(myDict[frozenset(Counter(('A', 'B')).items())]) # something else ,使其成为 hashable 。这将在用作键之前对值进行排序:(注意:元组中的所有内容必须可排序可哈希

sorted

但是如果元组元素既不是 hashable ,也不是可排序的,不幸的是,你可能运气不好,需要创建自己的dict结构。 .. D:

答案 1 :(得分:1)

您可以构建自己的结构:

class ReverseDict:
   def __init__(self):
      self.d = {}
   def __setitem__(self, k, v):
      self.d[k] = v

   def __getitem__(self, tup):
      return self.d[tup[::-1]]

myDict = ReverseDict()
myDict[('A', 'B')] = 'something'
myDict[('B', 'A')] = 'something else'
print(myDict[('A', 'B')])

输出:

something else

答案 2 :(得分:0)

我认为这里的要点是,元组的元素指向相同的字典元素,而不管它们的顺序如何。这可以通过使哈希函数在元组键元素上可交换来实现:

class UnorderedKeyDict(dict):
    def __init__(self, *arg):
        if arg:
            for k,v in arg[0].items():
                self[k] = v

    def _hash(self, tup):
        return sum([hash(ti) for ti in tup])

    def __setitem__(self, tup, value):
        super().__setitem__(self._hash(tup), value)

    def __getitem__(self, tup):
      return super().__getitem__(self._hash(tup))

mydict = UnorderedKeyDict({('a','b'):12,('b','c'):13})
mydict[('b','a')]
    >> 12