2013-01-06 50 views
20

Tôi có một danh sách các hàng tương tự như sau:tổng mỗi giá trị trong một danh sách các hàng

l = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 0)] 

Tôi muốn tạo ra một đơn giản một-liner mà sẽ cung cấp cho tôi những kết quả sau:

r = (25, 20) or r = [25, 20] # don't care if tuple or list. 

nào sẽ giống như cách làm như sau:

r = [0, 0] 
for t in l: 
    r[0]+=t[0] 
    r[1]+=t[1] 

tôi chắc chắn nó là một cái gì đó rất đơn giản, nhưng tôi không thể nghĩ về nó.

Lưu ý: Tôi nhìn câu hỏi tương tự đã:

How do I sum the first value in a set of lists within a tuple?

How do I sum the first value in each tuple in a list of tuples in Python?

+0

có thể du plicate của [Python element-wise tuple hoạt động như tổng hợp] (http://stackoverflow.com/questions/497885/python-element-wise-tuple-operations-like-sum) –

+0

@CiroSantilli: nó không phải là một bản sao. Câu hỏi mà bạn đã liên kết hoạt động với * hai * bộ dữ liệu. Câu hỏi này về danh sách * của bộ dữ liệu. Sự chuyển vị là phần thiết yếu của giải pháp. Mặc dù các câu trả lời làm việc gần như nguyên văn trong cả hai trường hợp. Tuy nhiên 'a, b' tuples và' a_list_of_tuples' khác nhau (sự khác biệt có thể được phơi bày trong giải pháp nào là hiệu quả nhất). – jfs

Trả lời

46

Sử dụng zip()sum():

In [1]: l = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 0)] 

In [2]: [sum(x) for x in zip(*l)] 
Out[2]: [25, 20] 

hay:

In [4]: map(sum, zip(*l)) 
Out[4]: [25, 20] 

timeit kết quả:

In [16]: l = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 0)]*1000 

In [17]: %timeit [sum(x) for x in zip(*l)] 
1000 loops, best of 3: 1.46 ms per loop 

In [18]: %timeit [sum(x) for x in izip(*l)]  #prefer itertools.izip 
1000 loops, best of 3: 1.28 ms per loop 

In [19]: %timeit map(sum, zip(*l)) 
100 loops, best of 3: 1.48 ms per loop 

In [20]: %timeit map(sum, izip(*l))    #prefer itertools.izip 
1000 loops, best of 3: 1.29 ms per loop 
+0

O_O không thể tin được nó đơn giản như thế nào, làm thế nào tôi có thể quên về 'zip'? cảm ơn. Đó là hiệu quả hơn? phương thức 'map' hoặc' list-comprehension'? –

+0

@Inbar kiểm tra và tìm hiểu. – Triptych

+1

'map' đôi khi hoạt động tốt hơn' list comprehension' khi được sử dụng với các hàm dựng sẵn. –

2

Tôi muốn thêm một cái gì đó để trả lời cho:

Nếu tôi có một loạt các ví dụ dict

l = [{'quantity': 10, 'price': 5},{'quantity': 6, 'price': 15},{'quantity': 2, 'price': 3},{'quantity': 100, 'price': 2}] 

và tôi muốn nhận hai (hoặc nhiều) khoản tiền được tính trên giá trị, ví dụ: tổng khối lượng và giá * số lượng

tôi có thể làm:

(total_quantity, total_price) = (
sum(x) for x in zip(*((item['quantity'], 
         item['price'] * item['quantity']) 
         for item in l))) 

Thay vì:

total_quantity = 0 
total_price = 0 
for item in l: 
    total_quantity += item['quantity'] 
    total_price += item['price'] * item['quantity'] 

Có lẽ giải pháp đầu tiên là ít có thể đọc được, nhưng là nhiều hơn "pythonesque" :)

+1

Điều gì sẽ thêm vào câu trả lời của Ashwini? Câu hỏi không phải là về một danh sách các dicts –

+1

bạn nói đúng, nhưng nó thêm một cái gì đó về cách sử dụng tổng và zip cho các hoạt động phức tạp. Tôi đã tìm kiếm một cái gì đó như thế, tôi đã tìm thấy câu trả lời này và tôi sử dụng nó cho vấn đề của riêng tôi, đó là về dicts. Do đó tôi nghĩ sẽ tốt hơn nếu chia sẻ giải pháp của tôi với ai đó có thể có cùng vấn đề với tôi. –

1

Không sử dụng zip

sum(e[0] for e in l), sum(e[1] for e in l) 
Các vấn đề liên quan