【问题标题】:Generate unique identifier for dictionary?为字典生成唯一标识符?
【发布时间】:2017-10-20 18:38:49
【问题描述】:

我有一个问题,我随机生成一个字典,可能有很多可能性(比如,我有 25'000 个可能不同的 dics)。我想为这些可能性中的每一种生成一个标识符,一个 ID。我想要的是:

  • 如果两个字典的每个键的值完全相同,则 ID 相同
  • 如果两个字典具有不同的 ID,则它们必须在内容上至少有一个差异。
  • 每次运行程序时 ID 都保持不变(id(x) 不起作用)
  • 奖励:对于不同版本的 Python(2.6、2.7、3.4、3.6),ID 保持不变

我目前的想法是使用哈希函数(虽然我对此了解甚少)并做这样的事情(假设一个整数/浮点数的字典):

import hashlib
def getID(mydic):
    ID = 0
    for x in mydic.keys():
        # Hash the content
        ID = ID + int(hashlib.sha256(str(mydic[x]).encode('utf-8')).hexdigest(), 16)
        # Hash the key
        ID = ID + int(hashlib.sha256(x.encode('utf-8')).hexdigest(), 16)
    return (ID % 10**10)

据我了解,这在大多数情况下应该有效,但根据字典和键的实际内容,两个不同的 dic 产生相同的 ID 并非不可能。例如,如果我不对键进行哈希处理,并且两个不同的条目可以是“1.0”,那么我可能会遇到问题。

你有什么建议,希望不要靠运气?

编辑:我在我正在尝试做的事情上添加了一个更大的代码:它基本上是一个随机参数优化。 Code on pastebin

【问题讨论】:

  • 你到底想达到什么目的?
  • 任何将大输入集映射到较小输入集的哈希都会发生冲突。所以总是有一点“运气”。你可以做的是:通过你的 id 比较字典。如果 id 不同,则 dicts 不同。如果 id 相同,则按值比较字典。
  • @tyteen4a03 我有一个算法,我想在多组参数上进行测试。我随机选择一组参数,然后运行我的算法——但我希望能够将该组参数保存到一个文件中,而不会被另一组覆盖,这样我就可以始终知道哪些参数导致了哪些结果。你想让我发布一个更大的代码吗,例如在 pastebin 上?
  • 如果你不局限于数字,那么我会做sha1(repr(sorted(my_dict.items())))(灵感来自this comment)。否则请参阅@Wombatz 的评论。
  • 问题,为什么字典的顺序很重要?

标签: python dictionary hash uniqueidentifier


【解决方案1】:

靠运气;其他人都这样做是有充分理由的。除非您的 ID 比您可以编码的最长字典长,或者您选择不能对某些字典进行编码,否则将有多个字典具有相同的 ID。这是一个简单的计数问题。假设您将一本字典命名为 1,然后再命名为 2,依此类推。要么你最终用完了号码,要么你的 ID 变得更长。 C通常,当我们想要一些代表对象的少量数量时,我们会使用 ID 或散列。如果您愿意让字典的名称与字典本身一样大,那么您正在寻找规范表示,而不是 ID 或哈希。

类似 sha256 的优点是我们认为很难找到两个具有相同哈希的输入。尽管理论上可以确定有多个输入给出相同的 sha256,但我们相信没有人发现两个输入给出相同的 sha256。 因此,您几乎可以肯定地足够安全,忽略遇到哈希冲突的可能性。

【讨论】:

  • 谢谢您,我可能会接受您的回答并依靠运气。快速提问,如果我要使用“规范表示”(我不知道那个词),我应该开始寻找什么?
  • 所以,这将是一个不同的问题,但看看canonicaljson 作为一个可能非常接近的例子
【解决方案2】:

要创建 ID,您需要创建一个非可变对象。 由于键是无序的,您可能需要对它们进行排序。

例如:

mydict = {'a': 1, 'c': 9, 'b': 3}

values = tuple(sorted(mydict.items()))
# -> (('a', 1), ('b', 3), ('c', 9))

然后,您可以使用自己的哈希算法,例如使用 sha256:

import hashlib

def hash_item(m, k, v):
    m.update(k.encode('utf-8'))
    m.update(str(k).encode('utf-8'))

m = hashlib.sha256()
for k, v in values:
    hash_item(m, k, v)
print(m.digest())
# -> b'\xa5\xb42\xee\x03\x07\xbe\x7f\xa2:\xa0\x04a\xf5N\xee4\xba\x9dE%\x1bU\x04V}7\xa8\xda3\x9d\xff'

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多