关于python:如何忽略元组中元素的顺序

how to ignore the order of elements in a tuple

我正在使用元组作为我创建的词典的键。例如:

1
2
example_dict = {}
example_dict[("A","B")] ="1"

稍后,当我希望修改字典中某个条目的值时,我目前无法控制元组的顺序。例如:

1
("B","A") may be the case, instead of ("A","B")

我知道这些元组不等于我在python shell中尝试的一个简单的==比较。

我想知道的是我如何解决这个问题?如何使以下内容不产生keyError:

1
print (example_dict["B","A"])

有没有一种方法可以一致地对元组的元素排序?有没有办法完全忽略订单?还有其他解决办法吗?我知道我可以将元组的所有排列都作为键包含在字典中,然后在以后整理不同排列的值。我强烈希望避免这样做,因为这只会增加问题的难度和复杂性。


通常的方法是对键进行排序:

1
example_dict[tuple(sorted(key_tuple))] ="1"

使用frozenset作为键(如果元组中没有重复的元素):

1
example_dict[frozenset(key_tuple)] ="1"

或者使用(item, count)元组的frozenset作为键(如果元组中可以有重复的元素):

1
example_dict[frozenset(Counter(key_tuple).viewitems())] ="1"

无论选择哪个选项,在查找值时都必须应用相同的转换。


您希望您的字典键是"集合"(集合是一个集合,对于该集合,项要么在集合中,要么不在集合中,但没有顺序概念)。幸运的是,python拥有您所需要的。具体来说,因为您需要一些可哈希的东西,所以您需要使用frozenset

1
2
3
4
5
6
>>> example_dict = {}
>>> example_dict[frozenset(("A","B"))] ="1"
>>> example_dict[frozenset(("B","A"))]
'1'
>>> example_dict[frozenset(("A","B"))]
'1'


不要使用tuple,而是使用frozenset。一个frozenset只是一个常数set,正如一个tuple可以被认为是一个常数list一样。

下面是一个示例(来自Python3,但它也将在Python2中工作):

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> d = {}
>>> k1 = frozenset((1, 2))
>>> k2 = frozenset((2, 1))
>>> k1
frozenset({1, 2})
>>> k2
frozenset({1, 2})
>>> k1 == k2
True
>>> d[k1] = 123
>>> d[k2]
123
>>>