Làm thế nào để thực hiện phép nhân phần tử của hai danh sách?


137

Tôi muốn thực hiện phép nhân phần tử một cách khôn ngoan, để nhân hai danh sách với nhau theo giá trị trong Python, giống như chúng ta có thể làm điều đó trong Matlab.

Đây là cách tôi sẽ làm điều đó trong Matlab.

a = [1,2,3,4]
b = [2,3,4,5]
a .* b = [2, 6, 12, 20]

Một danh sách hiểu biết sẽ cung cấp cho 16 mục danh sách, cho mỗi sự kết hợp x * ycủa xtừ aytừ b. Không chắc chắn làm thế nào để lập bản đồ này.

Nếu bất cứ ai quan tâm tại sao, tôi có một bộ dữ liệu và muốn nhân nó với Numpy.linspace(1.0, 0.5, num=len(dataset)) =).


4
Tại sao bạn hỏi điều này khi bạn bây giờ về numpy?
pwuertz

2
Và nhân tiện, đây là phép nhân yếu tố, đây không phải là một sản phẩm chấm.
pwuertz

3
Thay thế: map (lambda x, y: x * y, list1, list2) #derp ...
xxjjnn

Câu trả lời:


284

Sử dụng một danh sách hiểu được trộn với zip():.

[a*b for a,b in zip(lista,listb)]

9
Mặt khác, nếu họ muốn làm bất cứ điều gì khác ngoài trường hợp tầm thường ở đây, OP sẽ được khuyên nên sử dụng Numpy.
Henry Gomersall

1
Trên Python 2 izip () có thể là lựa chọn tốt hơn.
yak

23
Bạn cũng có thể sử dụng map(lambda x,y:x*y,lista,listb).
mbomb007

Câu trả lời sẽ thay đổi như thế nào nếu chúng ta được đưa ra thay vì listbmột danh sách các yếu tố thuộc loại listbđược đưa ra và chúng ta cần phải vận hành để có được một danh sách duy nhất. Ví dụ. (x, pi, e) với [(4, 5, 2), (1, 2, 4), (4, 5, 6), (1, 1, 2), (3, 3, 4)], khi lấy (x, pi, e) hoạt động với (4, 5, 2) và sau đó (x, pi, e) hoạt động với (1, 2, 4) ... cứ như vậy.
gxyd

@gxyd Bạn nên hỏi một câu hỏi riêng
mbomb007

87

Vì bạn đã sử dụng numpy, nên lưu trữ dữ liệu của bạn trong một numpymảng thay vì danh sách. Khi bạn làm điều này, bạn sẽ nhận được những thứ như các sản phẩm thông minh miễn phí:

In [1]: import numpy as np

In [2]: a = np.array([1,2,3,4])

In [3]: b = np.array([2,3,4,5])

In [4]: a * b
Out[4]: array([ 2,  6, 12, 20])

1
Có thể không phải là khoa học nhất, nhưng tôi đã hẹn giờ với câu trả lời của gahooa bằng cách sử dụng timeit. Numpy thực sự chậm hơn một chút so với phương pháp zip.
Chase Roberts

1
Trong trường hợp của tôi, trong đó các danh sách chứa các giá trị nhị phân, giải pháp numpy nhanh hơn nhiều so với sử dụng izip.
Serendipity

Vì lợi ích của những người khác đến đây từ một tìm kiếm google, tôi đã bao gồm một so sánh thời gian dưới đây.
thóc

31

Sử dụng np.multiply (a, b):

import numpy as np
a = [1,2,3,4]
b = [2,3,4,5]
np.multiply(a,b)

21

Bạn có thể thử nhân từng phần tử trong một vòng lặp. Bàn tay ngắn để làm điều đó là

ab = [a[i]*b[i] for i in range(len(a))]

Chào mừng đến với stackoverflow! câu trả lời chỉ có mã thường không được khuyến khích - vui lòng thêm một số giải thích về cách giải quyết câu hỏi của người hỏi.
Corley Brigman

7
@CorleyBrigman Tôi không đồng ý; có rất ít sự khác biệt giữa một câu trả lời là "Đây là một cách để làm điều này: <code>" và chỉ "<code>". Trong tình huống cụ thể này, có rất ít điều để giải thích ngoài "mã này giải quyết vấn đề của bạn".
icedtrees

4
@CorleyBrigman Tôi không đồng ý; một dữ liệu ví dụ với việc hiển thị kết quả sẽ thực sự hữu ích hơn
Tjorriemorrie

2
Đây là cách một lập trình viên C, C ++ hoặc Java là người mới làm quen với Python sẽ giải quyết vấn đề. Các câu trả lời được chấp nhận là thành ngữ Python.
David Cullen

@Tjorriemorrie kết quả rất rõ ràng vì chúng được yêu cầu rõ ràng trong câu hỏi. có thể một lời giải thích về cách hoạt động của việc hiểu danh sách có thể tốt hoặc đề cập rằng việc này sử dụng khả năng hiểu danh sách và sau đó mọi người có thể tra cứu điều đó, nếu họ không biết điều đó.
xuiqzy

10

Một câu trả lời khác:

-1... yêu cầu nhập khẩu
+1... rất dễ đọc

import operator
a = [1,2,3,4]
b = [10,11,12,13]

list(map(operator.mul, a, b))

đầu ra [10, 22, 36, 52]


Nếu bạn biết bản đồ, đây là một giải pháp thực sự dễ đọc! Việc nhập có bất kỳ hậu quả tiêu cực nào ngoài việc có ở đầu tập tin không? (các biên tập viên có thể ẩn nhập khẩu nếu họ muốn) Theo như tôi có thể thấy, nó nên có sẵn trong mọi phiên bản 2 và 3 của python!
xuiqzy

9

Cách khá trực quan để làm điều này:

a = [1,2,3,4]
b = [2,3,4,5]
ab = []                        #Create empty list
for i in range(0, len(a)):
     ab.append(a[i]*b[i])      #Adds each element to the list

9

bạn có thể nhân bằng cách sử dụng lambda

foo=[1,2,3,4]
bar=[1,2,5,55]
l=map(lambda x,y:x*y,foo,bar)

4

Đối với các danh sách lớn, chúng ta có thể thực hiện theo cách lặp:

product_iter_object = itertools.imap(operator.mul, [1,2,3,4], [2,3,4,5])

product_iter_object.next() đưa ra từng yếu tố trong danh sách đầu ra.

Đầu ra sẽ là độ dài ngắn hơn của hai danh sách đầu vào.


4

tạo ra một mảng của những cái; nhân mỗi danh sách nhân với mảng; chuyển mảng sang danh sách

import numpy as np

a = [1,2,3,4]
b = [2,3,4,5]

c = (np.ones(len(a))*a*b).tolist()

[2.0, 6.0, 12.0, 20.0]

3

Câu trả lời của gahooa là chính xác cho câu hỏi như cụm từ trong tiêu đề, nhưng nếu các danh sách có định dạng numpy hoặc lớn hơn mười thì sẽ nhanh hơn NHIỀU (3 bậc độ lớn) cũng như dễ đọc hơn, để thực hiện phép nhân đơn giản như được đề xuất bởi NPE. Tôi nhận được những thời gian này:

0.0049ms -> N = 4, a = [i for i in range(N)], c = [a*b for a,b in zip(a, b)]
0.0075ms -> N = 4, a = [i for i in range(N)], c = a * b
0.0167ms -> N = 4, a = np.arange(N), c = [a*b for a,b in zip(a, b)]
0.0013ms -> N = 4, a = np.arange(N), c = a * b
0.0171ms -> N = 40, a = [i for i in range(N)], c = [a*b for a,b in zip(a, b)]
0.0095ms -> N = 40, a = [i for i in range(N)], c = a * b
0.1077ms -> N = 40, a = np.arange(N), c = [a*b for a,b in zip(a, b)]
0.0013ms -> N = 40, a = np.arange(N), c = a * b
0.1485ms -> N = 400, a = [i for i in range(N)], c = [a*b for a,b in zip(a, b)]
0.0397ms -> N = 400, a = [i for i in range(N)], c = a * b
1.0348ms -> N = 400, a = np.arange(N), c = [a*b for a,b in zip(a, b)]
0.0020ms -> N = 400, a = np.arange(N), c = a * b

tức là từ chương trình kiểm tra sau.

import timeit

init = ['''
import numpy as np
N = {}
a = {}
b = np.linspace(0.0, 0.5, len(a))
'''.format(i, j) for i in [4, 40, 400] 
                  for j in ['[i for i in range(N)]', 'np.arange(N)']]

func = ['''c = [a*b for a,b in zip(a, b)]''',
'''c = a * b''']

for i in init:
  for f in func:
    lines = i.split('\n')
    print('{:6.4f}ms -> {}, {}, {}'.format(
           timeit.timeit(f, setup=i, number=1000), lines[2], lines[3], f))

3

Có thể sử dụng liệt kê.

a = [1, 2, 3, 4]
b = [2, 3, 4, 5]

ab = [val * b[i] for i, val in enumerate(a)]

3

Các mapchức năng có thể rất hữu ích ở đây. Sử dụng mapchúng ta có thể áp dụng bất kỳ chức năng nào cho từng phần tử của một lần lặp.

Python 3.x

>>> def my_mul(x,y):
...     return x*y
...
>>> a = [1,2,3,4]
>>> b = [2,3,4,5]
>>>
>>> list(map(my_mul,a,b))
[2, 6, 12, 20]
>>>

Tất nhiên:

map(f, iterable)

tương đương với

[f(x) for x in iterable]

Vì vậy, chúng tôi có thể nhận được giải pháp của chúng tôi thông qua:

>>> [my_mul(x,y) for x, y in zip(a,b)]
[2, 6, 12, 20]
>>>

Trong Python 2.x map()có nghĩa là: áp dụng một hàm cho từng phần tử của một lần lặp và xây dựng một danh sách mới. Trong Python 3.x, mapxây dựng các trình vòng lặp thay vì danh sách.

Thay vì my_mulchúng ta có thể sử dụng multoán tử

Python 2.7

>>>from operator import mul # import mul operator
>>>a = [1,2,3,4]
>>>b = [2,3,4,5]
>>>map(mul,a,b)
[2, 6, 12, 20]
>>>

Python 3,5+

>>> from operator import mul
>>> a = [1,2,3,4]
>>> b = [2,3,4,5]
>>> [*map(mul,a,b)]
[2, 6, 12, 20]
>>>

Xin lưu ý rằng vì map()xây dựng một trình vòng lặp, chúng tôi sử dụng *toán tử giải nén lặp để có được danh sách. Cách tiếp cận giải nén nhanh hơn một chút so với hàm listtạo:

>>> list(map(mul,a,b))
[2, 6, 12, 20]
>>>

1

Để duy trì loại danh sách và thực hiện trong một dòng (sau khi nhập numpy là np, tất nhiên):

list(np.array([1,2,3,4]) * np.array([2,3,4,5]))

hoặc là

list(np.array(a) * np.array(b))

0

bạn có thể sử dụng điều này cho các danh sách có cùng độ dài

def lstsum(a, b):
    c=0
    pos = 0
for element in a:
   c+= element*b[pos]
   pos+=1
return c
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.