Convertir un tableau numpy en tuple

108

Remarque: Ceci demande l'inverse de la conversion habituelle de tuple en tableau.

Je dois passer un argument à une fonction (c ++ enveloppée) en tant que tuple imbriqué. Par exemple, les travaux suivants

X = MyFunction( ((2,2),(2,-2)) )

alors que ce qui suit ne

X = MyFunction( numpy.array(((2,2),(2,-2))) )
X = MyFunction( [[2,2],[2,-2]] )

Malheureusement, l'argument que je voudrais utiliser me vient comme un tableau numpy. Ce tableau a toujours des dimensions 2xN pour certains N, qui peuvent être assez grands.

Existe-t-il un moyen simple de convertir cela en tuple? Je sais que je pourrais simplement faire une boucle, créer un nouveau tuple, mais préférerais s'il y a un accès agréable que le tableau numpy fournit.

S'il n'est pas possible de le faire aussi bien que je l'espère, quelle est la plus jolie façon de le faire en boucle, ou autre?

Mike
la source

Réponses:

157
>>> arr = numpy.array(((2,2),(2,-2)))
>>> tuple(map(tuple, arr))
((2, 2), (2, -2))
Niklas B.
la source
29
Donc, pour un simple tableau 1-dtuple(arr)
FindOutIslamNow
26

Voici une fonction qui le fera:

def totuple(a):
    try:
        return tuple(totuple(i) for i in a)
    except TypeError:
        return a

Et un exemple:

>>> array = numpy.array(((2,2),(2,-2)))
>>> totuple(array)
((2, 2), (2, -2))
Bi Rico
la source
1
Belle généralisation. En tant que débutant en python, cependant, je me demande s'il est considéré comme un bon style d'utiliser des exceptions pour une condition qui est presque aussi courante que l'état non exceptionnel. Au moins en C ++, le contrôle de flux par exceptions est généralement mal vu. Serait-il préférable de tester si type(a)==numpy.ndarray?
Mike
9
Ceci est assez courant en python à cause du concept de "canard-typing" et EAFT, plus ici: docs.python.org/glossary.html#term-duck-typing . L'avantage de cette approche est qu'elle convertira toute séquence imbriquée en tuples imbriqués, pas seulement un tableau. Une chose que j'aurais dû faire et que j'ai corrigée est de spécifier les erreurs que je souhaite gérer par le bloc except.
Bi Rico
3
En C ++, les exceptions sont lentes par rapport aux conditions pour diverses raisons. En Python, ils sont à peu près les mêmes en termes de performances - c'est l'un des endroits où nous devons vérifier nos intuitions C ++ à la porte.
dbn
8

Je n'étais pas satisfait, alors j'ai finalement utilisé ceci:

>>> a=numpy.array([[1,2,3],[4,5,6]])
>>> a
array([[1, 2, 3],
       [4, 5, 6]])

>>> tuple(a.reshape(1, -1)[0])
(1, 2, 3, 4, 5, 6)

Je ne sais pas si c'est plus rapide, mais ça a l'air plus efficace;)

en espérant que ça aide
la source
3
Ce n'était pas la forme que je voulais pour le tuple.
Mike
5

Une autre option

tuple([tuple(row) for row in myarray])

Si vous passez des tableaux NumPy à des fonctions C ++, vous pouvez également envisager d'utiliser Cython ou SWIG.

Greg von Winckel
la source
Cela ne se convertit pas en tuple. Convertit en liste?
Peter
Est-ce que tu l'as essayé? Il crée un tuple quand je cours. Notez que la dernière fonction appelée est tuple, qui renvoie un tuple. Si vous n'avez que la [...] partie sans le tuple externe, vous obtiendrez une liste de tuples.
Greg von Winckel
existe-t-il une méthode plus rapide?
Vicrobot
1
Vous pouvez éviter de créer l'intermédiaire listen omettant les crochets, c'est-à-dire en utilisanttuple(tuple(row) for row in myarray)
norok2
1

Si vous aimez les coupes longues, voici une autre façon tuple (tuple (a_m.tolist ()) pour a_m dans a)

from numpy import array
a = array([[1, 2],
           [3, 4]])
tuple(tuple(a_m.tolist()) for a_m in a )

La sortie est ((1, 2), (3, 4))

Notez que juste (tuple (a_m.tolist ()) pour a_m dans a) donnera une expression de générateur. Un peu inspiré par le commentaire de @ norok2 à la réponse de Greg von Winckel

Tejas Shetty
la source