如何在Python中为字典创建唯一键

Dan*_*ish 14 python hash dictionary

为字典内容生成唯一键的最佳方法是什么.我的目的是将每个字典与唯一的id或hash一起存储在文档存储中,这样我就不必从存储中加载整个字典来检查它是否已经存在.具有相同键和值的字典应生成相同的id或散列.

我有以下代码:

import hashlib

a={'name':'Danish', 'age':107}
b={'age':107, 'name':'Danish'}

print str(a)
print hashlib.sha1(str(a)).hexdigest()
print hashlib.sha1(str(b)).hexdigest()
Run Code Online (Sandbox Code Playgroud)

最后两个print语句生成相同的字符串.这是一个很好的实现吗?或者这种方法有什么缺陷吗?有一个更好的方法吗?

更新

结合以下答案的建议,以下可能是一个很好的实现

import hashlib

a={'name':'Danish', 'age':107}
b={'age':107, 'name':'Danish'}


def get_id_for_dict(dict):
    unique_str = ''.join(["'%s':'%s';"%(key, val) for (key, val) in sorted(dict.items())])
    return hashlib.sha1(unique_str).hexdigest()

print get_id_for_dict(a)
print get_id_for_dict(b)
Run Code Online (Sandbox Code Playgroud)

vam*_*min 34

我更喜欢将dict序列化为JSON并散列:

import hashlib
import json

a={'name':'Danish', 'age':107}
b={'age':107, 'name':'Danish'}

# Python 2
print hashlib.sha1(json.dumps(a, sort_keys=True)).hexdigest()
print hashlib.sha1(json.dumps(b, sort_keys=True)).hexdigest()

# Python 3
print(hashlib.sha1(json.dumps(a, sort_keys=True).encode()).hexdigest())
print(hashlib.sha1(json.dumps(b, sort_keys=True).encode()).hexdigest())
Run Code Online (Sandbox Code Playgroud)

返回:

71083588011445f0e65e11c80524640668d3797d
71083588011445f0e65e11c80524640668d3797d
Run Code Online (Sandbox Code Playgroud)


Tom*_*zky 8

不 - 在将字典转换为字符串时,您不能依赖于特定的元素顺序.

但是,您可以将其转换为(键,值)元组的排序列表,将其转换为字符串并计算如下的哈希:

a_sorted_list = [(key, a[key]) for key in sorted(a.keys())]
print hashlib.sha1( str(a_sorted_list) ).hexdigest()
Run Code Online (Sandbox Code Playgroud)

它不是万无一失的,因为转换为字符串的列表的格式化或元组的格式化可能会在未来的主要python版本中发生变化,排序顺序取决于语言环境等,但我认为它可以很好.

  • 更好的方法是使用`sorted(a.items())`然后你就可以将它折叠成一行而不会损失可读性. (6认同)

ubi*_*bik 3

一个可能的选择是使用保留顺序的列表的序列化表示。我不确定默认列表到字符串机制是否强加了任何类型的顺序,但如果它依赖于解释器,我也不会感到惊讶。所以,我基本上会构建一些类似于urlencode预先对键进行排序的东西。

并不是说我相信你的方法会失败,但我宁愿玩可预测的事情并避免无证和/或不可预测的行为。确实,尽管字典是“无序的”,但最终的顺序甚至可能是一致的,但重点是你不应该认为这是理所当然的。