Ubah larik numpy menjadi tupel

108

Catatan: Ini meminta kebalikan dari konversi tuple-ke-array biasa.

Saya harus meneruskan argumen ke fungsi (dibungkus c ++) sebagai tupel bersarang. Misalnya, karya berikut

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

sedangkan berikut ini tidak

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

Sayangnya, argumen yang ingin saya gunakan datang kepada saya sebagai array numpy. Larik tersebut selalu memiliki dimensi 2xN untuk beberapa N, yang mungkin cukup besar.

Apakah ada cara mudah untuk mengubahnya menjadi tupel? Saya tahu bahwa saya hanya dapat mengulang, membuat tupel baru, tetapi lebih suka jika ada akses bagus yang disediakan oleh numpy array.

Jika tidak mungkin melakukan ini sebaik yang saya harapkan, apa cara tercantik untuk melakukannya dengan mengulang, atau apa pun?

Mike
sumber

Jawaban:

157
>>> arr = numpy.array(((2,2),(2,-2)))
>>> tuple(map(tuple, arr))
((2, 2), (2, -2))
Niklas B.
sumber
29
Jadi untuk array 1-hari sederhanatuple(arr)
FindOutIslamNow
26

Inilah fungsi yang akan melakukannya:

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

Dan contoh:

>>> array = numpy.array(((2,2),(2,-2)))
>>> totuple(array)
((2, 2), (2, -2))
Bi Rico
sumber
1
Generalisasi yang bagus. Namun, sebagai pemula python, saya ingin tahu apakah itu dianggap gaya yang baik untuk menggunakan pengecualian untuk kondisi yang hampir sama umum dengan keadaan tidak luar biasa. Setidaknya di c ++, kontrol aliran dengan pengecualian biasanya tidak disukai. Apakah lebih baik untuk menguji jika type(a)==numpy.ndarray?
Mike
9
Ini cukup umum di python karena konsep "duck-mengetik" dan EAFT, selengkapnya di sini: docs.python.org/glossary.html#term-duck-typing . Keuntungan dari pendekatan ini adalah ia akan mengubah urutan bersarang apa pun menjadi tupel bersarang, bukan hanya sebuah array. Satu hal yang harus saya lakukan yang telah saya perbaiki adalah menentukan kesalahan mana yang ingin saya tangani oleh blok kecuali.
Bi Rico
3
Di C ++, pengecualian relatif lambat terhadap kondisional karena berbagai alasan. Dengan Python, mereka kira-kira sama dalam hal kinerja - ini adalah salah satu tempat di mana kita harus memeriksa intuisi C ++ kita di depan pintu.
dbn
8

Saya kurang puas, akhirnya saya pakai ini:

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

Saya tidak tahu apakah ini lebih cepat, tetapi kelihatannya lebih efektif;)

berharap itu membantu
sumber
3
Itu bukanlah bentuk yang saya inginkan untuk tupel tersebut.
Mike
5

Pilihan lain

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

Jika Anda meneruskan array NumPy ke fungsi C ++, Anda mungkin juga ingin melihat menggunakan Cython atau SWIG.

Greg von Winckel
sumber
Itu tidak diubah menjadi tupel. Mengonversi ke daftar?
Peter
Apakah kamu sudah mencobanya? Itu membuat tupel ketika saya masuk. Perhatikan bahwa fungsi terakhir yang dipanggil adalah tupel, yang mengembalikan tupel. Jika Anda hanya memiliki bagian [...] tanpa tupel luar, Anda akan mendapatkan daftar tupel.
Greg von Winckel
apakah ada metode yang lebih cepat?
Vicrobot
1
Anda dapat menghindari pembuatan perantara listdengan menghilangkan tanda kurung siku, yaitu menggunakantuple(tuple(row) for row in myarray)
norok2
1

Jika Anda suka potongan panjang, berikut adalah cara lain tuple (tuple (a_m.tolist ()) untuk a_m di a)

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

Outputnya adalah ((1, 2), (3, 4))

Perhatikan saja (tuple (a_m.tolist ()) untuk a_m dalam a) akan memberikan ekspresi generator. Semacam terinspirasi oleh komentar @ norok2 untuk jawaban Greg von Winckel

Tejas Shetty
sumber