Bất kỳ thuật toán băm nào thực sự thực hiện công việc của nó một cách chính xác sẽ sử dụng thời gian O (len (b)). Vì vậy, câu trả lời cho "là có cách nào nhanh hơn để làm điều này" là không.
Nếu mối quan tâm thực tế của bạn là sử dụng bộ nhớ, sau đó, về nguyên tắc, bạn có thể thêm phương thức __hash__
vào một lớp con của dấu gạch ngang. Nhưng đó là một ý tưởng khá tồi. Hãy xem điều gì xảy ra:
>>> class HashableBytearray(bytearray):
... def __hash__(self):
... return hash(str(self))
...
>>> h = HashableBytearray('abcd')
>>> hash(h)
-2835746963027601024
>>> h[2] = 'z'
>>> hash(h)
-2835746963002600949
Vì vậy, cùng một đối tượng có thể băm thành hai điểm khác nhau trong từ điển, điều này không được phép xảy ra. Và nó trở nên tồi tệ hơn:
>>> d = dict()
>>> hb1 = HashableBytearray('abcd')
>>> hb2 = HashableBytearray('abcd')
>>> d[hb1] = 0
>>> d[hb2] = 1
>>> d
{bytearray(b'abcd'): 1}
Ok, cho đến nay, rất tốt. Các giá trị bằng nhau, vì vậy chỉ nên có một mục trong từ điển. Mọi thứ đều hoạt động như mong đợi. Bây giờ chúng ta hãy xem những gì sẽ xảy ra khi chúng ta thay đổi hb1
:
Xem cách mặc dù hb2
không thay đổi chút nào, nó tạo ra một cặp khóa-giá trị mới trong từ điển thời gian này?
Mỗi lần tôi chuyển một khóa đến d
, khóa đó bằng 'abcd'
. Nhưng vì giá trị của khóa đầu tiên đã thay đổi sau khi thêm vào từ điển, Python không thể biết rằng giá trị của khóa mới giống với khóa cũ đã được thêm vào khi nó được thêm vào. Bây giờ có hai cặp khóa-giá trị trong từ điển, khi chỉ nên có một cặp.
Đây chỉ là một trong nhiều cách sử dụng các giá trị có thể thay đổi làm khóa có thể dẫn đến hành vi không thể đoán trước và rất sai. Chỉ cần chuyển đổi bytearray
thành loại không thay đổi được hoặc hoạt động với các loại bất biến ngay từ đầu.
Và đối với sự tò mò: chắc chắn, buffer
lưu trữ băm đầu tiên, nhưng điều đó không giúp gì cả. Chỉ có hai giá trị quan trọng, vì vậy đây sẽ tạo ra chỉ có hai mục dict:
>>> a, b, c = bytearray('abcd'), bytearray('abcd'), bytearray('abzd')
>>> a_buf, b_buf, c_buf = buffer(a), buffer(b), buffer(c)
>>> d = {b_buf:1, c_buf:2}
>>> b[2] = 'z'
>>> d[a_buf] = 0
Nhưng nó tạo ra ba:
>>> d
{<read-only buffer for 0x1004a2300, size -1, offset 0 at 0x100499cb0>: 1,
<read-only buffer for 0x1004a2420, size -1, offset 0 at 0x100499cf0>: 0,
<read-only buffer for 0x1004a22d0, size -1, offset 0 at 0x100499c70>: 2}
Bạn xử lý các va chạm băm như thế nào? – Cameron
Vấn đề không phải là va chạm, đó là những gì sẽ xảy ra nếu bạn thay đổi khóa. – FogleBird
Bạn đang sử dụng phiên bản Python nào? – jedwards