2009-12-21 6 views

Antwort

17

Wenn Sie eine Reihe der Elemente wollen, hier ist eine andere, wahrscheinlich schneller w ay:

y = set(x.flatten()) 

PS: Nach dem Vergleich zwischen x.flat, x.flatten() und x.ravel() auf einem 10x100 Array durchgeführt wird, habe ich herausgefunden, dass sie alle mit etwa der gleichen Geschwindigkeit durchführen. Für ein 3x3-Array, ist die schnellste Variante die Iterator Version:

y = set(x.flat) 

was ich empfehlen würde, weil es die weniger Speicher teuer Version (es skaliert gut mit der Größe des Arrays).

PS: Es gibt auch Funktion eines NumPy ist, die etwas ähnliches tut:

Dies produziert eine NumPy Array mit dem gleichen Elemente wie set(x.flat), sondern als NumPy Array

y = numpy.unique(x) 
. Dies ist sehr schnell (fast 10-mal schneller), aber wenn Sie eine set benötigen, dann ist set(numpy.unique(x)) ein bisschen langsamer als die anderen Verfahren (Aufbau eines Satzes kommt mit einem großen Aufwand).

+2

Guter Vorschlag! Sie könnten auch set (x.ravel()) verwenden, was dasselbe tut, aber nur bei Bedarf eine Kopie erstellt. Oder, besser, benutze set (x.flat). x.flat ist ein Iterator über die Elemente des abgeflachten Arrays, vergeudet aber keine Zeit, das Array tatsächlich zu verflachen – musicinmybrain

+0

@musicinmybrain: sehr gute Punkte! Vielen Dank! – EOL

+2

ACHTUNG: Diese Antwort * gibt Ihnen nicht eine Reihe von Vektoren, sondern eine Reihe von Zahlen. Wenn Sie eine Reihe von Vektoren haben wollen, sehen Sie sich die Antwort von Miku an, die die Vektoren in Tupel umwandelt: – conradlee

9

Das unveränderliche Pendant zu einem Array ist das Tupel, daher versuchen, das Array von Arrays in ein Array von Tupeln konvertieren:

>> from numpy import * 
>> x = array([[3,2,3],[4,4,4]]) 

>> x_hashable = map(tuple, x) 

>> y = set(x_hashable) 
set([(3, 2, 3), (4, 4, 4)]) 
+0

und wie ich leicht/effizient umwandeln zurück in eine Liste? – user989762

+0

'map (array, y)' – Manuel

3

Wenn Sie eine Reihe der Elemente wollen:

>> y = set(e for r in x 
      for e in r) 
set([2, 3, 4]) 

Für einen Satz der Zeilen:

>> y = set(tuple(r) for r in x) 
set([(3, 2, 3), (4, 4, 4)]) 
6

Die obigen Antworten arbeiten, wenn Sie einen Satz aus den Elemente in einem ndarray enthalten erstellen möchten, aber wenn Sie möchten, eine Reihe von ndarray Objekte erstellen - oder ndarray Objekte als Schlüssel in einem Wörterbuch verwenden - Sie dann Ich muss ihnen eine waschbare Hülle geben. Sehen Sie den Code für ein einfaches Beispiel:

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 

die Wrapper-Klasse zu verwenden ist einfach genug:

>>> 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'