[英]Multiples-keys dictionary where key order doesn't matter
I am trying to create a dictionary with two strings as a key and I want the keys to be in whatever order. 我正在尝试创建一个包含两个字符串作为键的字典,我希望键可以按任何顺序排列。
myDict[('A', 'B')] = 'something'
myDict[('B', 'A')] = 'something else'
print(myDict[('A', 'B')])
I want this piece of code to print 'something else'. 我想要这段代码打印“别的东西”。 Unfortunately, it seems that the ordering matters with tuples. 不幸的是,似乎订单与元组有关。 What would be the best data structure to use as the key? 什么是最好的数据结构作为关键?
frozenset
使用frozenset
Instead of a tuple
, which is ordered, you can use a frozenset
, which is unordered , while still hashable as frozenset
is immutable . 代替的tuple
,这是命令,你可以使用一个frozenset
,这是无序的 ,同时仍然可哈希作为frozenset
是不可改变的 。
myDict = {}
myDict[frozenset(('A', 'B'))] = 'something'
myDict[frozenset(('B', 'A'))] = 'something else'
print(myDict[frozenset(('A', 'B'))])
Which will print: 哪个会打印:
something else
Unfortunately, this simplicity comes with a disadvantage, since frozenset
is basically a “frozen” set. 不幸的是,这种简单性带来了一个缺点,因为frozenset
基本上是一个“冻结”的集合。 There will be no duplicate values in the frozenset
, for example, 例如, frozenset
没有重复值
frozenset((1, 2)) == frozenset((1,2,2,1,1))
If the trimming down of values doesn't bother you, feel free to use frozenset
如果削减值不会打扰您,请随意使用frozenset
But if you're 100% sure that you don't want what was mentioned above to happen, there are however two alternates: 但如果你100%确定你不想要上面提到的内容发生,那么有两个替代方案:
First method is to use a Counter
, and make it hashable
by using frozenset
again: ( Note: everything in the tuple must be hashable ) 第一种方法是使用一个Counter
,并使其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
Second method is to use the built-in function sorted
, and make it hashable by making it a tuple
. 第二种方法是使用内置函数sorted
,并通过使其成为tuple
使其可哈希 。 This will sort the values before being used as a key: ( Note: everything in the tuple must be sortable and hashable ) 这将在用作键之前对值进行排序:( 注意:元组中的所有内容都必须是可排序和可清除的 )
myDict = {}
myDict[tuple(sorted(('A', 'B')))] = 'something'
myDict[tuple(sorted(('B', 'A')))] = 'something else'
print(myDict[tuple(sorted(('A', 'B')))])
# something else
But if the tuple elements are neither all hashable , nor are they all sortable , unfortunately, you might be out of luck and need to create your own dict structure... D: 但是,如果元组元素既不是可以清洗的 ,也不是可以排序的 ,不幸的是,你可能运气不好,需要创建自己的dict结构...... D:
You can build your own structure: 您可以构建自己的结构:
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')])
Output: 输出:
something else
I think the point here is that the elements of the tuple point to the same dictionary element regardless of their order. 我认为这里的要点是元组的元素指向相同的字典元素,而不管它们的顺序如何。 This can be done by making the hash function commutative over the tuple key elements: 这可以通过使哈希函数在元组关键元素上交换来完成:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.