如何将Python中同一索引中的数组的每个数字相乘?

How to multiply each digit of an array in the same index in Python?

我必须编写这样的程序来乘以一个: 第一个数组的第一个列表的第一个数字与第二个数组的第一个列表的第一个数字。例如:

Input
array1 = [[1,2,3], [3,2,1]]
array2 = [[4,2,5], [5,6,7]]

所以我的输出必须是:

result = [[4,4,15],[15,12,7]]

到目前为止我的代码如下:

def multiplyArrays(array1,array2):
    if verifySameSize(array1,array2):
        for i in array1:
            for j in i:
                digitA1 = j
            for x in array2:
                for a in x:
                    digitA2 = a
            mult = digitA1 * digitA2
        return mult
    return 'Arrays must be the same size'

可以肯定地说它不起作用,因为我给出的示例得到的结果是 7,甚至不是数组,所以,我做错了什么?

您可以使用 zip() 同时遍历列表:

array1 = [[1,2,3], [3,2,1]]
array2 = [[4,2,5], [5,6,7]]

def multiplyArrays(array1,array2):
    result = []
    for inner1,inner2 in zip(array1,array2):
        inner = []
        for item1,item2 in zip(inner1,inner2):
            inner.append(item1*item2)
        result.append(inner)
    return result

print(multiplyArrays(array1,array2))

按要求输出。

如果您想要一个简单的解决方案,请使用 numpy:

import numpy as np

array1 = np.array([[1,2,3], [3,2,1]])
array2 = np.array([[4,2,5], [5,6,7]])

result = array1 * array2

如果您想要一个通用的解决方案以供您自己理解,那么它会变得有点困难:in-depth您希望实现方式如何?有很多检查,例如相同的尺寸、相同的类型、尺寸的数量等。

您的代码中的问题是使用 for each 循环而不是索引。 for i in array1 运行两次,返回一个列表(首先是 [1,2,3],然后是 [3,2,1])。然后你在每个列表中做一个 for each 循环返回一个数字,这意味着你只得到 1 个数字作为输出,这是最后一个操作的结果 (1 * 7 = 7)。您应该创建一个空列表并将您的结果附加到正常的 for 循环中(不是每个)。

所以你的函数变成:

def multiplyArrays(array1,array2):
    result = []
    for i in range(len(array1)):
        result.append([])
        for j in range(len(array1[i])):
            result[i].append(array1[i][j]*array2[i][j])
    return result

虽然这是个坏主意,因为它只适用于二维数组并且没有检查。除非绝对需要,否则避免编写自己的函数。

这里有三个 pure-Python one-liners 可以产生您预期的输出,其中两个只是其他两个答案的列表理解版本。列表理解等效项通常更有效,但您应该选择最适合您的内容。

方法一 @quamrana's,作为列表理解。

res = [[a * b for a, b in zip(c, d)] for c, d in zip(arr1, arr2)]

方法 2@OM222O 的,作为列表理解。

res = [[ arr1[i][j] * arr2[i][j] for j in range(len(arr1[0])) ] for i in range(len(arr1))]

方法三 与方法一类似,但使用了operator.mul(a, b) (returns a * b) from the operator module and the built-in map(function, iterable, ...)函数。 map 函数“[r]eturn[s] 一个迭代器,它将函数应用于可迭代的每个项目,产生结果。”因此,给定两个列表 a(来自 array1)和 b(来自 array2),map(operator.mul, a, b) returns 一个产生乘法结果的迭代器a 中的每个元素与 b 中的元素具有相同的索引。 list() 将结果转换为列表。

res = [list(map(operator.mul, a, b)) for a, b in zip(arr1, arr2)]

简单基准测试


输入

from random import randint

arr1 = [[randint(1, 25) for i in range(1_000)] for j in range(1_000)]
arr2 = [[randint(1, 25) for i in range(1_000)] for j in range(1_000)]

从最快到最慢排序

# Method 3
29.2 ms ± 59.1 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# Method 1
44.4 ms ± 197 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# Method 2
79.3 ms ± 151 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# numpy multiplication (inclusive of time required to convert list to array)
81.7 ms ± 122 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

我们可以看到方法 3(operator.mul 方法)最快,而 numpy 方法最慢。当然,有一个很大的警告,因为 numpy 时间包括将列表转换为数组所需的时间。为了进行有意义的比较,我们需要指定输入and/or输出是否为列表and/or数组。显然,如果输入已经是列表并且结果也必须是列表,那么我们可以对标准 Python 方法感到满意。

但是,如果 arr1arr2 已经是 numpy 数组,element-wise 乘法速度非常快:

1.47 ms ± 5.2 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

不使用任何模块的更简单的方法。

array1 = [[1, 2, 3], [3, 2, 1]]
array2 = [[4, 2, 5], [5, 6, 7]]

result = []

i = 0 
while i < len(array1):
    sub_array1 = array1[i]
    sub_array2 = array2[i]

    a, b, c = sub_array1
    d, e, f = sub_array2

    inner_list = [a * d, b * e, c * f]
    result.append(inner_list)

    i += 1

print(result)

输出:

[[4,4,15],[15,12,7]]