【问题标题】:Make a list of ints hashable in python在python中制作一个可散列的整数列表
【发布时间】:2016-05-02 11:41:46
【问题描述】:

我有一个整数列表,我想在 python 字典中用作键。我正在缓存一个函数的结果,该函数将整数列表作为输入。我目前的解决方案:

list_of_ints = [1,20,3,4]
key = str(sorted(list_of_ints))[1:-1].replace(' ','')

生成密钥“1,3,4,20”。似乎应该有一种更快/更漂亮/更pythonic的方式来做到这一点。

【问题讨论】:

标签: python hash


【解决方案1】:

只需使用元组作为键。元组是不可变且可散列的,因此它们可用作字典键。

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_

它应该给你一个唯一的(非常大的!)整数来存储,它在内存中比元组小。如果可以避免,请不要这样做——它非常不透明。


在您提到的 cmets 中,您的键中不会有重复的值,因此 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.Freeley 总是有 4 个整数吗?
  • 不,可变长度。
  • 与订单无关的“容器”如果实现为frozenset(...) 而不是tuple(sorted(...)) 可能会更好。话虽如此,您的容器仍然缺少一堆方法——.pop.get.setdefault 以及我目前不记得的其他方法。 . .
  • 是的,我不应该有重复值,所以我认为frozenset 是我正在寻找的答案。
【解决方案2】:

你也可以创建哈希列表。

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)

现在可以了:

hash(hash_list(1, 2, 3))

hash(hash_list([1, 2, 3]))

【讨论】:

  • 可能是个愚蠢的问题,但如果您要将类型更改为生成器,为什么不只使用元组?
  • @SujalSingh 有时您需要可变且同时可散列的序列。
猜你喜欢
  • 2019-08-26
  • 2017-10-02
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
  • 2012-10-02
  • 2012-04-20
  • 1970-01-01
  • 2019-05-09
相关资源
最近更新 更多