Những câu trả lời ở trên có tác dụng nếu bạn muốn tạo một bộ ra khỏi yếu tố chứa trong một ndarray
, nhưng nếu bạn muốn tạo ra một tập hợp các ndarray
đối tượng - hoặc sử dụng ndarray
đối tượng như phím trong một cuốn từ điển - sau đó bạn sẽ phải cung cấp một wrapper hashable cho chúng. Xem mã dưới đây cho một ví dụ đơn giản:
from hashlib import sha1
from numpy import all, array, uint8
class hashable(object):
r'''Hashable wrapper for ndarray objects.
Instances of ndarray are not hashable, meaning they cannot be added to
sets, nor used as keys in dictionaries. This is by design - ndarray
objects are mutable, and therefore cannot reliably implement the
__hash__() method.
The hashable class allows a way around this limitation. It implements
the required methods for hashable objects in terms of an encapsulated
ndarray object. This can be either a copied instance (which is safer)
or the original object (which requires the user to be careful enough
not to modify it).
'''
def __init__(self, wrapped, tight=False):
r'''Creates a new hashable object encapsulating an ndarray.
wrapped
The wrapped ndarray.
tight
Optional. If True, a copy of the input ndaray is created.
Defaults to False.
'''
self.__tight = tight
self.__wrapped = array(wrapped) if tight else wrapped
self.__hash = int(sha1(wrapped.view(uint8)).hexdigest(), 16)
def __eq__(self, other):
return all(self.__wrapped == other.__wrapped)
def __hash__(self):
return self.__hash
def unwrap(self):
r'''Returns the encapsulated ndarray.
If the wrapper is "tight", a copy of the encapsulated ndarray is
returned. Otherwise, the encapsulated ndarray itself is returned.
'''
if self.__tight:
return array(self.__wrapped)
return self.__wrapped
Sử dụng lớp wrapper là đơn giản đủ:
>>> from numpy import arange
>>> a = arange(0, 1024)
>>> d = {}
>>> d[a] = 'foo'
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: unhashable type: 'numpy.ndarray'
>>> b = hashable(a)
>>> d[b] = 'bar'
>>> d[b]
'bar'
Đề xuất tốt! Bạn cũng có thể sử dụng set (x.ravel()), thực hiện điều tương tự nhưng chỉ tạo một bản sao nếu cần. Hoặc, tốt hơn, sử dụng set (x.flat). x.flat là một iterator trên các phần tử của mảng phẳng, nhưng không lãng phí thời gian thực sự làm phẳng mảng – musicinmybrain
@musicinmybrain: các điểm rất tốt! Cảm ơn bạn! – EOL
CẢNH BÁO: câu trả lời này * sẽ không * cung cấp cho bạn một tập hợp các vectơ, mà là tập hợp các số. Nếu bạn muốn một tập hợp các vectơ thì hãy xem câu trả lời của miku bên dưới để chuyển đổi các vectơ thành bộ dữ liệu – conradlee