Перетворити масивний масив в кортеж


108

Примітка. Це вимагає зворотного перетворення звичайного перетворення каналу в масив.

Я маю передавати аргумент функції (обгорнутого c ++) як вкладений кортеж. Наприклад, такі праці

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

тоді як наступне не робить

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

На жаль, аргумент, який я хотів би використати, приходить до мене як нумерований масив. Цей масив завжди має розміри 2xN для деяких N, які можуть бути досить великими.

Чи є простий спосіб перетворити це на кортеж? Я знаю, що я міг би просто пройти цикл, створивши новий кортеж, але я вважаю за краще, якщо є якийсь приємний доступ до нумерованого масиву.

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

Відповіді:



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
Гарне узагальнення. Як новачок з пітонів, мені цікаво, чи вважається гарним стилем використання винятків для умови, яка майже така ж поширена, як і невиключний стан. Принаймні, в c ++, контроль потоку за винятками, як правило, нахмуриться. Було б краще перевірити, якщо type(a)==numpy.ndarray?
Майк

9
Це досить часто зустрічається в python через концепцію "набору качок" та EAFT, докладніше тут: docs.python.org/glossary.html#term-duck-typing . Перевага такого підходу полягає в тому, що він перетворить будь-яку вкладену послідовність у вкладені кортежі, а не лише масив. Одне, що я мав би зробити, що я виправив, - це вказати, які помилки я хочу обробляти за винятком блоку.
Бі-Ріко

3
У C ++ винятки є повільними щодо умовних умов з різних причин. У Python вони приблизно однакові за показниками продуктивності - це одне з місць, що нам доводиться перевіряти наші інтуїції C ++ біля дверей.
дбн

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 (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 до відповіді Грега фон Вінкеля

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.