Преобразование массива numpy в кортеж

108

Примечание: требуется обратное обычному преобразованию кортежа в массив.

Мне нужно передать аргумент функции (обернутой c ++) как вложенный кортеж. Например, следующие работы

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

в то время как следующее не

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

К сожалению, аргумент, который я хотел бы использовать, приходит ко мне в виде массива numpy. Этот массив всегда имеет размеры 2xN для некоторого N, что может быть довольно большим.

Есть ли простой способ преобразовать это в кортеж? Я знаю, что могу просто пройти цикл, создав новый кортеж, но предпочел бы, если есть хороший доступ, который предоставляет массив numpy.

Если это невозможно сделать так хорошо, как я надеюсь, какой самый красивый способ сделать это с помощью цикла или чего-то еще?

Майк
источник

Ответы:

157
>>> arr = numpy.array(((2,2),(2,-2)))
>>> tuple(map(tuple, arr))
((2, 2), (2, -2))
Никлас Б.
источник
29
Итак, для простого tuple(arr)
одномерного
26

Вот функция, которая это сделает:

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

И пример:

>>> array = numpy.array(((2,2),(2,-2)))
>>> totuple(array)
((2, 2), (2, -2))
Би-Рико
источник
1
Хорошее обобщение. Однако, как новичок в Python, мне интересно, считается ли хорошим стилем использовать исключения для условий, которые почти так же распространены, как и неисключительное состояние. По крайней мере, в C ++ управление потоком с помощью исключений обычно не одобряется. Было бы лучше проверить, если type(a)==numpy.ndarray?
Майк
9
Это довольно часто встречается в Python из-за концепции «утиного ввода» и EAFT, подробнее здесь: docs.python.org/glossary.html#term-duck-typing . Преимущество этого подхода в том, что он преобразует любую вложенную последовательность во вложенные кортежи, а не только в массив. Одна вещь, которую я должен был исправить, - это указать, какие ошибки я хочу обрабатывать с помощью блока except.
Би-Рико
3
В C ++ исключения работают медленнее по сравнению с условными операторами по разным причинам. В Python они примерно одинаковы с точки зрения производительности - это одно из тех мест, где мы должны проверить нашу интуицию C ++ на пороге.
dbn
8

Мне это не понравилось, поэтому я наконец использовал это:

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

Не знаю, быстрее ли, но выглядит эффективнее;)

надеюсь, что это поможет
источник
3
Это была не та форма, которую я хотел для кортежа.
Майк
5

Другой вариант

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

Если вы передаете массивы NumPy функциям C ++, вы также можете использовать Cython или SWIG.

Грег фон Винкель
источник
Это не преобразуется в кортеж. Преобразует в список?
Питер,
Вы пробовали? Когда я вбегаю, он создает кортеж. Обратите внимание, что последней вызываемой функцией является кортеж, который возвращает кортеж. Если у вас есть только часть [...] без внешнего кортежа, вы получите список кортежей.
Грег фон Винкель,
есть более быстрый способ?
Vicrobot
1
Вы можете избежать создания промежуточного звена list, опустив квадратные скобки, то есть используяtuple(tuple(row) for row in myarray)
norok2
1

Если вам нравятся длинные сокращения, вот еще один способ tuple (tuple (a_m.tolist ()) для a_m в a)

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

Результатом будет ((1, 2), (3, 4))

Обратите внимание, что просто (tuple (a_m.tolist ()) для a_m в a) даст выражение генератора. Вроде как вдохновленный комментарием @ norok2 к ответу Грега фон Винкеля

Теджас Шетти
источник