แปลง numpy array เป็น tuple


108

หมายเหตุ:สิ่งนี้กำลังขอการย้อนกลับของการแปลง tuple-to-array ตามปกติ

ฉันต้องส่งอาร์กิวเมนต์ไปยังฟังก์ชัน (wrap c ++) เป็นทูเพิลที่ซ้อนกัน ตัวอย่างเช่นงานต่อไปนี้

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

ในขณะที่สิ่งต่อไปนี้ทำไม่ได้

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

น่าเสียดายที่อาร์กิวเมนต์ที่ฉันต้องการใช้เป็นอาร์เรย์ที่เป็นตัวเลข อาร์เรย์นั้นมีขนาด 2xN เสมอสำหรับ N บางตัวซึ่งอาจมีขนาดค่อนข้างใหญ่

มีวิธีง่ายๆในการแปลงเป็นทูเปิลหรือไม่? ฉันรู้ว่าฉันสามารถวนซ้ำสร้างทูเพิลใหม่ได้ แต่ต้องการถ้ามีการเข้าถึงที่ดีที่อาร์เรย์ numpy ให้

ถ้าเป็นไปไม่ได้ที่จะทำสิ่งนี้ให้ดีเท่าที่ฉันหวังไว้วิธีใดที่สวยที่สุดในการทำโดยการวนลูปหรืออะไรก็ตาม

คำตอบ:



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ไหมถ้าจะทดสอบว่า?
Mike

9
นี้สวยที่พบบ่อยในหลามเพราะแนวคิดของ "เป็ดพิมพ์" และ EAFT มากขึ้นที่นี่: docs.python.org/glossary.html#term-duck-typing ข้อดีของวิธีนี้คือจะแปลงลำดับที่ซ้อนกันเป็นสิ่งที่ซ้อนกันไม่ใช่แค่อาร์เรย์ สิ่งหนึ่งที่ฉันควรทำเพื่อแก้ไขคือระบุข้อผิดพลาดที่ฉันต้องการจัดการโดยบล็อกยกเว้น
Bi Rico

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
นั่นไม่ใช่รูปร่างที่ฉันต้องการสำหรับทูเปิล
Mike

5

อีกทางเลือกหนึ่ง

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

หากคุณกำลังส่งอาร์เรย์ NumPy ไปยังฟังก์ชัน C ++ คุณอาจต้องการดูการใช้ Cython หรือ SWIG


นั่นไม่ได้แปลงเป็นทูเปิล แปลงเป็นรายการ?
Peter

คุณลองหรือยัง? มันสร้างทูเพิลเมื่อฉันเรียกใช้โปรดทราบว่าฟังก์ชันสุดท้ายที่เรียกว่าทูเพิลซึ่งส่งคืนทูเพิล หากคุณมีเฉพาะส่วน [... ] โดยไม่มีทูเพิลด้านนอกคุณจะได้รับรายชื่อทูเพิล
Greg von Winckel

มีวิธีที่เร็วกว่านี้ไหม
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 ต่อคำตอบของ Greg von Winckel

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.