2008-11-04 27 views
33

Tôi khá chắc chắn nên có một cách Pythonic hơn để làm điều này - nhưng tôi không thể nghĩ ra một: Làm thế nào tôi có thể hợp nhất một danh sách hai chiều thành một danh sách một chiều? Sắp xếp giống như zip/map nhưng với nhiều hơn hai vòng lặp.Việc hợp nhất/thêm danh sách bằng Python

Ví dụ - Tôi đã danh sách sau đây:

array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 

Tôi muốn có

result = [12, 15, 18] # [1+4+7, 2+5+8, 3+6+9] 

Cho đến nay những gì tôi đã đưa ra là:

def add_list(array): 
    number_items = len(array[0]) 
    result = [0] * number_items 
    for index in range(number_items): 
     for line in array: 
      result[index] += line[index] 
    return result 

Nhưng đó trông không thật tao nhã/Pythonic với tôi. Ngoài việc không kiểm tra xem tất cả các "dòng" trong mảng 2D có cùng chiều dài, có thể được thêm vào nhau hay không, vv Điều gì sẽ là một cách tốt hơn để làm điều đó?

Trả lời

69
[sum(a) for a in zip(*array)] 
63

[tổng (giá trị) cho giá trị trong zip (* mảng)] khá chuẩn.

này có thể giúp bạn hiểu nó:

In [1]: array=[[1, 2, 3], [4, 5, 6], [7, 8, 9]] 

In [2]: array 
Out[2]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 

In [3]: *array 
------------------------------------------------------------ 
    File "<ipython console>", line 1 
    *array 
    ^
<type 'exceptions.SyntaxError'>: invalid syntax 

Ngôi sao unary không phải là một nhà điều hành của chính nó. Nó mở các phần tử mảng thành các đối số thành các cuộc gọi hàm.

In [4]: zip(*array) 
Out[4]: [(1, 4, 7), (2, 5, 8), (3, 6, 9)] 

zip() là một built-in chức năng

In [5]: zip(*array)[0] 
Out[5]: (1, 4, 7) 

mỗi phần tử cho danh sách được trả về bởi zip là một tập hợp các số bạn muốn.

In [6]: sum(zip(*array)[0]) 
Out[6]: 12 

In [7]: [sum(values) for values in zip(*array)] 
Out[7]: [12, 15, 18] 
8

Nếu bạn đang làm rất nhiều loại điều, bạn muốn tìm hiểu về scipy.

>>> import scipy 
>>> sum(scipy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) 
array([12, 15, 18]) 

Tất cả kích thước mảng được kiểm tra cho bạn tự động. Tổng được thực hiện trong C tinh khiết, vì vậy nó rất nhanh. Các mảng scipy cũng rất hiệu quả về bộ nhớ.

Hạn chế là bạn đang phụ thuộc vào một mô-đun bên thứ ba khá phức tạp. Nhưng đó là một sự cân bằng rất tốt cho nhiều mục đích.

14

Một cách khác:

map(sum, zip(*array)) 
3

Đồng ý với fivebells, nhưng bạn cũng có thể sử dụng NumPy, mà là một nhỏ hơn (nhập khẩu nhanh hơn) và thực hiện chung chung hơn thứ mảng như thế nào. (thực sự, nó là một phụ thuộc của scipy). Đây là những công cụ tuyệt vời, như đã được nói, là một 'phải sử dụng' nếu bạn đối phó với loại thao tác này.

2

muộn để các trò chơi, và nó không phải là tốt đẹp của một câu trả lời như một số người khác, nhưng tôi nghĩ rằng nó là loại dễ thương:

map(lambda *x:sum(x),*array) 

nó quá xấu mà sum(1,2,3) không hoạt động.Nếu nó đã làm, chúng ta có thể loại bỏ ngớ ngẩn lambda trong đó, nhưng tôi cho rằng sẽ làm cho nó khó khăn để phân biệt (nếu có) của các yếu tố là "bắt đầu" của tổng. Bạn sẽ phải thay đổi điều đó thành một từ khóa chỉ tranh luận sẽ phá vỡ rất nhiều kịch bản ... Oh well. Tôi đoán chúng ta sẽ chỉ sống với lambda.

0

[sum (a) cho một trong zip (* mảng)]

tôi thích điều đó. Tôi cần một cái gì đó liên quan cho đan xen đối tượng vào một danh sách các mục, đã đưa ra một cái gì đó tương tự nhưng ngắn gọn hơn cho thậm chí danh sách dài:

sum(zip(*array),()) 

ví dụ, đan xen hai danh sách:

a = [1,2,3] 
b = ['a','b','c'] 
sum(zip(a,b),()) 
(1, 'a', 2, 'b', 3, 'c') 
+0

Hm, trong khi thú vị, đó không thực sự là câu trả lời cho câu hỏi này (và do đó có thể thu hút những người không thích). Bạn có thể, ví dụ, đặt câu hỏi "Làm thế nào tôi có thể xen kẽ một số danh sách?" và tự trả lời. Có thể sử dụng một ví dụ sử dụng nhiều hơn hai danh sách, nếu không ai đó sẽ gợi ý '", ". Join (a)'. –

+0

Đồng ý Tim. Đó là các apropros của 'q & a' này được chỉ ra bởi một luồng giao dịch các danh sách xen kẽ, nhưng được đánh dấu là một bản sao của câu hỏi này! Tôi đã sử dụng ',' trong ví dụ, chỉ để đơn giản, mã của tôi yêu cầu danh sách thực sự của các lớp do người dùng định nghĩa để xen kẽ, nhưng điều đó sẽ khó có thể tha thứ trong tóm tắt. – F1Rumors

0

Bạn có thể chỉ đơn giản là làm điều này:

print [sum(x) for x in zip(*array)] 

Nếu bạn muốn lặp thông qua danh sách theo cách này, bạn có thể sử dụng chain của module itertools:

from itertools import chain 

for x in array.chain.from_iterable(zip(*array)): 
    print x 
# prints 1, 4, 7, 2, 5, 8, ... 
Các vấn đề liên quan