Les réponses ci-dessus fonctionnent si vous voulez créer un ensemble sur des éléments contenus dans un ndarray
, mais si vous voulez créer un ensemble de ndarray
objets - ou utiliser ndarray
objets comme les clés dans un dictionnaire - vous Je vais devoir leur fournir une enveloppe pouvant être lavée. Voir le code ci-dessous pour un exemple simple:
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
Utilisation de la classe d'emballage est assez simple:
>>> 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'
Bonne suggestion! Vous pouvez également utiliser set (x.ravel()), qui fait la même chose mais ne crée une copie que si nécessaire. Ou, mieux, utilisez set (x.flat). x.flat est un itérateur sur les éléments du tableau aplati, mais ne perd pas de temps à réellement aplatir le tableau – musicinmybrain
@musicinmybrain: de très bons points! Je vous remercie! – EOL
ATTENTION: cette réponse * ne vous * donnera pas un ensemble de vecteurs, mais plutôt un ensemble de nombres. Si vous voulez un ensemble de vecteurs, voyez la réponse de miku ci-dessous qui convertit les vecteurs en tuples – conradlee