我有一个整数列表,我想用作python词典中的键.我正在缓存一个以int的列表作为输入的函数的结果.我目前的解决方案
list_of_ints = [1,20,3,4]
key = str(sorted(list_of_ints))[1:-1].replace(' ','')
Run Code Online (Sandbox Code Playgroud)
它产生关键'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", ...}
Run Code Online (Sandbox Code Playgroud)
值得注意的是,他们关心订单,因此[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
Run Code Online (Sandbox Code Playgroud)
不要试图自己序列化它.如果你这样做,不要使用字符串操作 - 它太难看了.如果您真诚地感到内存匮乏或者您拥有成千上万的这些记录,那么您可以通过序列化来节省微不足道的空间:
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_
Run Code Online (Sandbox Code Playgroud)
这应该给你一个唯一的(难以置信的大!)整数存储,它将在内存中小于元组.如果你能避免它,不要这样做 - 它是非常不透明的.
在你提到的评论中,你不会在密钥中有重复的值,所以frozenset
肯定是你正在寻找的.
d = {}
list_of_ints = [1, 20, 3, 4]
d[frozenset(list_of_ints)] = "some value"
Run Code Online (Sandbox Code Playgroud)
frozenset
对象是不可变的类似于哈希set
的对象.它们与订单无关,并且忽略重复.
您还可以创建可哈希列表。
from 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)
Run Code Online (Sandbox Code Playgroud)
现在这有效了:
hash(hash_list(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)
或者
hash(hash_list([1, 2, 3]))
Run Code Online (Sandbox Code Playgroud)