2013-04-18 43 views
9

Cách tốt nhất để tạo khóa duy nhất cho nội dung của từ điển là gì. Ý định của tôi là lưu trữ từng từ điển trong một cửa hàng tài liệu cùng với một id hoặc băm duy nhất để tôi không phải tải toàn bộ từ điển từ cửa hàng để kiểm tra xem nó có tồn tại hay không. Từ điển có cùng khóa và giá trị phải tạo cùng một id hoặc băm.Cách tạo khóa duy nhất cho từ điển trong Python

Tôi có đoạn mã sau:

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() 

Hai báo cáo in cuối cùng tạo ra các chuỗi tương tự. Đây có phải là triển khai tốt không? hoặc có bất kỳ cạm bẫy với cách tiếp cận này? Có cách nào tốt hơn để làm điều này?

Cập nhật

gợi ý kết hợp từ các câu trả lời dưới đây, sau đây có thể là một thực hiện tốt

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

thực hiện của bạn trong bản cập nhật là rất sai: thử điều này: 'get_id_for_dict ({ 'foo':' bar '}) 'hoặc' get_id_for_dict ({' fo ':' obar '}) 'hoặc' get_id_for_dict ({' f ':' o ',' o ':' bar '}) '. Tất cả đều trả về '8843d7f92416211de9ebb963ff4ce28125932878'. Sử dụng tốt hơn 'unique_str = join (['% s% s'% (hashlib.sha1 (khóa), hashlib.sha1 (val)) cho (key, val) trong sắp xếp (dict.items())])' – Tometzky

+0

@ Tometzky Cảm ơn bạn đã chỉ ra sai lầm của tôi. Tôi đã thử đề xuất của bạn, nhưng nó không thành công nếu các khóa hoặc giá trị không thuộc loại chuỗi. Thay vào đó, tôi chỉ thay đổi định dạng chuỗi để bao bọc khóa & giá trị trong dấu ngoặc kép và đặt ký tự đại tràng giữa chúng – Danish

+0

Vẫn không tốt nếu có thể có ''', ':' và ';' trong khóa hoặc giá trị. Sử dụng 'unique_str = join (['% s% s'% (hashlib.sha1 (str (khóa)), hashlib.sha1 (str (val))) cho (key, val) trong sắp xếp (dict.items()) ]) ' – Tometzky

Trả lời

3

Một lựa chọn có thể sẽ được sử dụng một đại diện tuần tự của danh sách mà giữ gìn trật tự. Tôi không chắc liệu danh sách mặc định cho cơ chế chuỗi có áp đặt bất kỳ loại lệnh nào không, nhưng nó sẽ không làm tôi ngạc nhiên nếu nó phụ thuộc vào thông dịch viên. Vì vậy, tôi về cơ bản sẽ xây dựng một cái gì đó giống như urlencode mà sắp xếp các phím trước.

Không phải là tôi tin rằng phương pháp của bạn sẽ thất bại, nhưng tôi thích chơi với những điều có thể dự đoán được và tránh hành vi không có giấy tờ và/hoặc không thể đoán trước. Đúng là mặc dù "không có thứ tự", các từ điển cuối cùng vẫn có một trật tự thậm chí có thể nhất quán, nhưng vấn đề là bạn không nên lấy điều đó một cách nhất quán.

+0

Tôi thích ứng, tôi không rõ ràng. Ý định của tôi là từ điển có cùng khóa và giá trị nên tạo cùng một id hoặc băm – Danish

+0

-1. Từ đọc của tôi về câu hỏi, mã định danh duy nhất nên dựa trên nội dung của từ điển. –

+0

@StevenRumbalski Pedro đã trả lời trước khi tôi thêm phần giải thích của tôi vào câu hỏi. – Danish

7

Không - you can't rely on particular order of elements when converting dictionary to a string.

Bạn có thể, tuy nhiên, chuyển đổi nó vào danh sách được sắp xếp của (key, value) tuples, chuyển đổi nó thành một chuỗi và tính toán một hash như thế này:

a_sorted_list = [(key, a[key]) for key in sorted(a.keys())] 
print hashlib.sha1(str(a_sorted_list)).hexdigest() 

Nó không fool-proof, như một Formating của một danh sách được chuyển đổi thành một chuỗi hoặc định dạng của một bộ tuple có thể thay đổi trong một số phiên bản python chính trong tương lai, thứ tự sắp xếp phụ thuộc vào miền địa phương vv nhưng tôi nghĩ nó có thể đủ tốt.

+5

Tốt hơn là sử dụng 'sắp xếp (a.items())', sau đó bạn có thể thu gọn thành một lớp lót mà không mất khả năng đọc. –

23

Tôi thích serializing dict như JSON và băm rằng:

import hashlib 
import json 

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

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

Returns:

71083588011445f0e65e11c80524640668d3797d 
71083588011445f0e65e11c80524640668d3797d 
+0

Cảm ơn! Đây là một giải pháp thanh lịch thực sự, mà sẽ chăm sóc của sự khác biệt giữa '{'b': 'ar'; 'f': 'oo'}' và '{'b': 'ar', 'f': 'oo' } 'là tốt. – Danish

Các vấn đề liên quan