我正在尝试创建一个包含两个字符串作为键的字典,我希望键可以按任何顺序排列。
myDict[('A', 'B')] = 'something'
myDict[('B', 'A')] = 'something else'
print(myDict[('A', 'B')])
我希望这段代码能够打印“别的东西”。不幸的是,似乎订单与元组有关。什么是最好的数据结构用作关键?
答案 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