การดำเนินการทูเพิลที่ชาญฉลาดของ Python เช่น sum


102

จะมีการดำเนินการ tuple ใน Python ให้ทำงานเช่นนี้หรือไม่:

>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(4,4,4)

แทน:

>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(1,2,3,3,2,1)

ฉันรู้ว่ามันทำงานแบบนั้นเพราะมีการกำหนด__add__และ__mul__วิธีการให้ทำงานเช่นนั้น ดังนั้นวิธีเดียวที่จะกำหนดพวกเขาใหม่?

คำตอบ:


138
import operator
tuple(map(operator.add, a, b))

4
ฉันจะบอกว่านี่เป็นวิธีแก้ปัญหาแบบไพ ธ อนที่สุด
Matthew Schinckel

3
ยกเว้นแผนที่ () เลิกใช้งานแล้ว ดูartima.com/weblogs/viewpost.jsp?thread=98196สำหรับบทความโดย Guido ซึ่งกล่าวถึงวิธีการเขียนแผนที่ให้ดีขึ้นในฐานะรายการเพื่อความเข้าใจ
Adam Parkin

นอกจากนี้ยังจะระเบิดหาก a & b ไม่มีองค์ประกอบจำนวนเท่ากันหรือไม่ "เพิ่มได้" (เช่นmap(operator.add, (1,2), ("3", "4"))
Adam Parkin

24
tuple([item1 + item2 for item1, item2 in zip(a, b)])จะเทียบเท่ากับความเข้าใจรายการ
Adam Parkin

13
@AdamParkin, comprehensions tuple(item1 + item2 for item1, item2 in zip(a, b))กำเนิดที่ดียิ่งขึ้น
Cristian Ciupitu

121

ใช้บิวท์อินทั้งหมด ..

tuple(map(sum, zip(a, b)))

2
นี่ดูเหมือนจะเป็นคำตอบที่ง่ายและดีกว่า ทำไมถึงไม่รับ?
Marc Cenedella

15
เป็นเรื่องดี แต่ในทางเทคนิคไม่ใช่สิ่งที่ขอเพราะแผนที่ส่งคืนรายการไม่ใช่ทูเปิล ... ดังนั้น:tuple(map(sum,zip(a,b))
เบ็

3
ไวยากรณ์เป็นเรื่องลึกลับ
anatoly techtonik

2
ประโยชน์ของสิ่งนี้คือคุณสามารถขยายไปถึง:tuple(map(sum,zip(a,b, c))
Andy Hayden

33

โซลูชันนี้ไม่ต้องการการนำเข้า:

tuple(map(lambda x, y: x + y, tuple1, tuple2))

3
โซลูชันนี้ยังเร็วกว่าโซลูชันแบบไม่นำเข้าแบบซับเดียว ( map(sum, zip(a, b)))
อากาศ

20

เรียงลำดับจากสองคำตอบแรกที่รวมเข้าด้วยกันด้วยการปรับแต่งรหัสของ ironfroggy เพื่อให้ส่งคืนทูเพิล:

import operator

class stuple(tuple):
    def __add__(self, other):
        return self.__class__(map(operator.add, self, other))
        # obviously leaving out checking lengths

>>> a = stuple([1,2,3])
>>> b = stuple([3,2,1])
>>> a + b
(4, 4, 4)

หมายเหตุ: ใช้self.__class__แทนstupleการแบ่งคลาสย่อย


18
from numpy import array

a = array( [1,2,3] )
b = array( [3,2,1] )

print a + b

ให้array([4,4,4]).

ดูhttp://www.scipy.org/Tentative_NumPy_Tutorial


9
วิธีนี้จะได้ผล แต่มันค่อนข้างหนักในการนำเข้า numpy เพียงเพื่อการดำเนินการเพิ่มเติมง่ายๆ

11

สามารถใช้ความเข้าใจของเครื่องกำเนิดไฟฟ้าแทนแผนที่ ฟังก์ชั่นแผนที่ในตัวไม่ล้าสมัย แต่คนส่วนใหญ่อ่านได้น้อยกว่าความเข้าใจรายการ / ตัวสร้าง / คำสั่งดังนั้นฉันไม่แนะนำให้ใช้ฟังก์ชันแผนที่โดยทั่วไป

tuple(p+q for p, q in zip(a, b))

6

วิธีง่ายๆที่ไม่มีการกำหนดคลาสที่ส่งคืนทูเพิล

import operator
tuple(map(operator.add,a,b))

6

โซลูชันเครื่องกำเนิดไฟฟ้าทั้งหมด ไม่แน่ใจในประสิทธิภาพ (itertools เร็ว แต่)

import itertools
tuple(x+y for x, y in itertools.izip(a,b))

3

ใช่. แต่คุณไม่สามารถกำหนดประเภทบิวท์อินใหม่ได้ คุณต้อง subclass:

คลาส MyTuple (ทูเพิล):
    def __add __ (ตัวเองอื่น ๆ ):
         ถ้า len (ตัวเอง)! = len (อื่น ๆ ):
             เพิ่ม ValueError ("ความยาวทูเปิลไม่ตรงกัน")
         ส่งคืน MyTuple (x + y สำหรับ (x, y) ใน zip (ตัวเอง, อื่น ๆ ))

แต่คุณไม่สามารถใช้ไวยากรณ์ทูเพิลได้
airportyh


1

ขณะนี้ฉันย่อยคลาส "ทูเพิล" เพื่อโอเวอร์โหลด +, - และ * ฉันพบว่ามันทำให้โค้ดสวยงามและเขียนโค้ดได้ง่ายขึ้น

class tupleN(tuple):
    def __add__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x+y for x,y in zip(self,other))
    def __sub__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x-y for x,y in zip(self,other))
    def __mul__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x*y for x,y in zip(self,other))


t1 = tupleN((1,3,3))
t2 = tupleN((1,3,4))
print(t1 + t2, t1 - t2, t1 * t2, t1 + t1 - t1 - t1)
(2, 6, 7) (0, 0, -1) (1, 9, 12) (0, 0, 0)

-1

ในกรณีที่มีคนต้องการหาค่าเฉลี่ยรายการสิ่งที่ติดตาม:

import operator 
from functools import reduce
tuple(reduce(lambda x, y: tuple(map(operator.add, x, y)),list_of_tuples))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.