为字典内容生成唯一键的最佳方法是什么。我的目的是将每个字典与唯一的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()
最后两个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)
答案 0 :(得分:31)
我更喜欢将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())
返回:
71083588011445f0e65e11c80524640668d3797d
71083588011445f0e65e11c80524640668d3797d
答案 1 :(得分:8)
不 - you can't rely on particular order of elements when converting dictionary to a string。
但是,您可以将其转换为(键,值)元组的排序列表,将其转换为字符串并计算如下的哈希值:
a_sorted_list = [(key, a[key]) for key in sorted(a.keys())]
print hashlib.sha1( str(a_sorted_list) ).hexdigest()
这不是万无一失的,因为转换为字符串的列表的格式化或元组的格式化可能会在未来的主要python版本中发生变化,排序顺序取决于区域设置等,但我认为它足够好。< / p>
答案 2 :(得分:3)
可能的选项是使用保留顺序的列表的序列化表示。我不确定字符串机制的默认列表是否会强加任何类型的顺序,但如果它是依赖于解释器的话,我也不会感到惊讶。所以,我基本上会构建类似于事先对键进行排序的urlencode
。
并不是说我相信你的方法会失败,但我宁愿玩可预测的事情并避免无证和/或不可预测的行为。确实,尽管“无序”,词典最终会得到一个甚至可能一致的订单,但重点是你不应该认为这是理所当然的。