![](/img/trans.png)
[英]How to multiply each row in a matrix by each column in the second matrix in Python?
[英]compare each row with each column in matrix using only pure python
我有一个我制作的 function,我想在矩阵的每一列和每一行上运行它,以检查是否有行和列产生相同的 output。
例如:
matrix = [[1,2,3],
[7,8,9]]
我想运行 function,我们称之为myfun
,在每一列[1,7]
、 [2,8]
和[3,9]
上分别运行,并且在每一行[1,2,3]
和[7,8,9]
。 如果有一行和一列产生相同的结果,计数器ct
将 go 增加 1。所有这些都可以在另一个 function 中找到,称为count_good
,它基本上计算产生相同结果的行和列。
这是到目前为止的代码:
def count_good(mat):
ct = 0
for i in mat:
for j in mat:
if myfun(i) == myfun(j):
ct += 1
return ct
但是,当我使用 print 检查我的代码时,我得到了这个:
mat = [[1,2,3],[7,8,9]]
for i in mat:
for j in mat:
print(i,j)
[1, 2, 3] [1, 2, 3]
[1, 2, 3] [7, 8, 9]
[7, 8, 9] [1, 2, 3]
[7, 8, 9] [7, 8, 9]
我看到代码没有返回我需要的'这意味着count_good
function 将不起作用。 如何在每一行和每一列上运行 function? 我需要在没有任何外部库帮助的情况下做到这一点,没有map
、 zip
或类似的东西,只有非常纯的 python。
让我们从使用itertools
和collections
开始,然后将其转换回“纯” python。
from itertools import product, starmap, chain # combinations?
from collections import Counter
要有效地迭代嵌套循环,您可以使用itertools.product
。 您也可以使用starmap
扩展 function 的 arguments。 这是myfun
在行上的值的生成器:
starmap(myfun, product(matrix, repeat=2))
要转置矩阵并遍历列,请使用zip(*
习惯用法:
starmap(myfun, product(zip(*matrix), repeat=2))
您可以使用collections.Counter
to map 每个可能的返回值的所有重复:
Counter(starmap(myfun, chain(product(matrix, repeat=2), product(zip(*matrix), repeat=2))))
如果您想避免在相同元素上运行myfun
,请将product(..., repeat=2)
替换为combinations(..., 2)
。
现在您已经了解了如何执行此操作,请将所有外部库的内容替换为等效的内置函数:
counter = {}
for i in range(len(matrix)):
for j in range(len(matrix)):
result = myfun(matrix[i], matrix[j])
counter[result] = counter.get(result, 0) + 1
for i in range(len(matrix[0])):
for j in range(len(matrix[0])):
c1 = [matrix[row][i] for row in range(len(matrix))]
c2 = [matrix[row][j] for row in range(len(matrix))]
result = myfun(c1, c2)
counter[result] = counter.get(result, 0) + 1
如果您想要组合,请将循环对替换为
for i in range(len(...) - 1):
for j in range(i + 1, len(...)):
使用本机 python:
def count_good(mat):
ct = 0
for row in mat:
for col_idx in range(len(mat[0])):
column = [x[col_idx] for x in mat]
if myfun(row) == myfun(column):
ct += 1
return ct
但是,这是非常低效的,因为它是一个三重嵌套的 for 循环。 我建议改用 numpy。
例如
def count_good(mat):
ct = 0
mat = np.array(mat)
for row in mat:
for column in mat.T:
if myfun(row) == myfun(column):
ct += 1
return ct
TL;博士
要从 N 个 M 元素列表的 2D 列表中获取一列,首先将列表展平为 N×M 元素的 1D 列表,然后从 1D 列表中选择步幅等于 M(列数)的元素,为您提供原始二维列表的一列。
首先,我创建一个随机整数矩阵,作为等长列表的列表——这里我从“纯”Python 的目标中获得一些自由,OP 可能会手动输入一些分配的矩阵。
from random import randrange, seed
seed(20220914)
dim = 5
matrix = [[randrange(dim) for column in range(dim)] for row in range(dim)]
print(*matrix, sep='\n')
我们需要将 function 应用于矩阵的每一行和每一列,我打算将其作为列表提供。 在这里,我选择了一个简单的元素总和。
def myfun(l_st):
the_sum = 0
for value in l_st: the_sum = the_sum+value
return the_sum
为了继续,我们将做一些意想不到的事情,即我们展开矩阵,从一个空列表开始,我们对行进行循环并将当前行“求和”为unwrapped
,请注意,将两个列表相加会给您一个列表包含两个列表的所有元素。
unwrapped = []
for row in matrix: unwrapped = unwrapped+row
下面我们将需要矩阵中的列数,这个数字可以通过计算矩阵最后一行中的元素来计算。
ncols = 0
for value in row: ncols = ncols+1
现在,我们可以计算将myfunc
应用于每一列产生的值,计算我们有多少次相同的值。
我们使用一个辅助变量start
,它初始化为零并在以下循环的每次迭代中递增,它使用一个虚拟变量扫描当前行的所有元素,因此start
的值为0, 1, ..., ncols-1
,因此unwrapped[start::ncols]
是一个列表,正好包含矩阵的一列。
count_of_column_values = {}
start = 0
for dummy in row:
column_value = myfun(unwrapped[start::ncols])
if column_value not in count_of_column_values:
count_of_column_values[column_value] = 1
else:
count_of_column_values[column_value] = count_of_column_values[column_value] + 1
start = start+1
此时,我们已准备好将myfun
应用于行
count = 0
for row in matrix:
row_value = myfun(row)
if row_value in count_of_column_values: count = count+count_of_column_values[row_value]
print(count)
执行上面的代码打印
[1, 4, 4, 1, 0]
[1, 2, 4, 1, 4]
[1, 4, 4, 0, 1]
[4, 0, 3, 1, 2]
[0, 0, 4, 2, 2]
3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.