我有一个整数列表,我想在Python字典中将其用作键。我正在缓存从接受整数列表作为输入的函数(s)返回的结果。我的当前解决方案:
list_of_ints = [1,20,3,4]
key = str(sorted(list_of_ints))[1:-1].replace(' ','')
生成键'1,3,4,20'。似乎应该有一种更快/更漂亮/更Pythonic的方法来做这个。
只需使用元组作为键。元组是不可变的且可哈希化的,因此它们作为字典键非常有用。
list_of_ints = [1, 20, 3, 4]
# tuple(list_of_ints) == (1, 20, 3, 4)
some_dict = {tuple(list_of_ints): "some value", ...}
值得注意的是,它们确实关心顺序,所以[1, 20, 3, 4]
与[1, 3, 20, 4]
不会产生相同的值。
你甚至可以创建一个容器来帮助你做到这一点。
class MyDict(dict):
def __getitem__(self, key):
key = tuple(sorted(key))
return super().__getitem__(key)
# similar for pop, get, setdefault, update....
>>> d = MyDict()
>>> d[1,2,3] = 4
>>> d[3,2,1]
4
不要试图自己序列化它。如果您这样做,不要使用字符串操作——那太丑陋了。如果您真的缺乏内存,或者您有数十万条这些记录,您可以像这样进行序列化以节省无关紧要的空间:
def my_serialize(key_nums: list):
key_nums = sorted(key_nums)
base = max(key_nums)
sum_ = 0
for power, num in enumerate(key_nums):
sum_ += base**power * num
return sum_
如果你需要存储一个比元组更小的独特(非常大!)整数,可以使用此方法。不建议使用此方法,因为它非常难以理解。
根据你在评论中提到的关键字不会有重复值,因此frozenset
绝对是你要找的。
d = {}
list_of_ints = [1, 20, 3, 4]
d[frozenset(list_of_ints)] = "some value"
frozenset
对象是不可变的、可哈希的类似于set
的对象。它们不考虑顺序并忽略重复项。
key=tuple(sorted(list_of_ints))
- I.P. Freeleyfrozenset(...)
而不是tuple(sorted(...))
。话虽如此,您的容器仍然缺少许多方法——.pop
、.get
、.setdefault
和可能还有其他我暂时想不起来的方法... - mgilsonfrozenset
就是我要找的答案。 - I.P. Freeleyfrom collections import Iterable
class hash_list(list):
def __init__(self, *args):
if len(args) == 1 and isinstance(args[0], Iterable):
args = args[0]
super().__init__(args)
def __hash__(self):
return hash(e for e in self)
现在这个功能可以使用:
hash(hash_list(1, 2, 3))
或者
hash(hash_list([1, 2, 3]))
frozenset
作为键值(参考链接:https://dev59.com/R14b5IYBdhLWcg3w5VP9)。 - Chris Martin