在python中添加两个矩阵

ger*_*erg 14 python nested-lists

我正在尝试编写一个函数,添加两个矩阵来传递以下doctests:

  >>> a = [[1, 2], [3, 4]]
  >>> b = [[2, 2], [2, 2]]
  >>> add_matrices(a, b)
  [[3, 4], [5, 6]]
  >>> c = [[8, 2], [3, 4], [5, 7]]
  >>> d = [[3, 2], [9, 2], [10, 12]]
  >>> add_matrices(c, d)
  [[11, 4], [12, 6], [15, 19]]
Run Code Online (Sandbox Code Playgroud)

所以我写了一个函数:

def add(x, y):
    return x + y
Run Code Online (Sandbox Code Playgroud)

然后我写了以下函数:

def add_matrices(c, d):
    for i in range(len(c)):
        print map(add, c[i], d[i])
Run Code Online (Sandbox Code Playgroud)

排序的得到正确的答案.

nin*_*cko 21

矩阵库

您可以使用numpy支持此功能的模块.

>>> import numpy as np

>>> a = np.matrix([[1, 2], [3, 4]])
>>> b = np.matrix([[2, 2], [2, 2]])

>>> a+b
matrix([[3, 4],
        [5, 6]])
Run Code Online (Sandbox Code Playgroud)

本土解决方案:重量级

假设您想自己实现它,您将设置以下机制,这将允许您定义任意成对操作:

from pprint import pformat as pf

class Matrix(object):
    def __init__(self, arrayOfRows=None, rows=None, cols=None):
        if arrayOfRows:
            self.data = arrayOfRows
        else:
            self.data = [[0 for c in range(cols)] for r in range(rows)]
        self.rows = len(self.data)
        self.cols = len(self.data[0])

    @property
    def shape(self):          # myMatrix.shape -> (4,3)
        return (self.rows, self.cols)
    def __getitem__(self, i): # lets you do myMatrix[row][col
        return self.data[i]
    def __str__(self):        # pretty string formatting
        return pf(self.data)

    @classmethod
    def map(cls, func, *matrices):
        assert len(set(m.shape for m in matrices))==1, 'Not all matrices same shape'

        rows,cols = matrices[0].shape
        new = Matrix(rows=rows, cols=cols)
        for r in range(rows):
            for c in range(cols):
                new[r][c] = func(*[m[r][c] for m in matrices], r=r, c=c)
        return new
Run Code Online (Sandbox Code Playgroud)

现在添加成对方法就像派对一样简单:

    def __add__(self, other):
        return Matrix.map(lambda a,b,**kw:a+b, self, other)
    def __sub__(self, other):
        return Matrix.map(lambda a,b,**kw:a-b, self, other)
Run Code Online (Sandbox Code Playgroud)

例:

>>> a = Matrix([[1, 2], [3, 4]])
>>> b = Matrix([[2, 2], [2, 2]])
>>> b = Matrix([[0, 0], [0, 0]])

>>> print(a+b)
[[3, 4], [5, 6]]                                                                                                                                                                                                      

>>> print(a-b)
[[-1, 0], [1, 2]]
Run Code Online (Sandbox Code Playgroud)

你甚至可以添加成对求幂,否定,二元运算等.我在这里没有演示它,因为最好留下*和**用于矩阵乘法和矩阵求幂.


本土解决方案:轻量级

如果您只想要一种非常简单的方法来仅在两个嵌套列表矩阵上映射操作,则可以执行以下操作:

def listmatrixMap(f, *matrices):
    return \
        [
            [
                f(*values) 
                for c,values in enumerate(zip(*rows))
            ] 
            for r,rows in enumerate(zip(*matrices))
        ]
Run Code Online (Sandbox Code Playgroud)

演示:

>>> listmatrixMap(operator.add, a, b, c))
[[3, 4], [5, 6]]
Run Code Online (Sandbox Code Playgroud)

使用额外的if-else和keyword参数,您可以在lambda中使用索引.下面是如何编写矩阵行顺序enumerate函数的示例.为清楚起见,上面省略了if-else和关键字.

>>> listmatrixMap(lambda val,r,c:((r,c),val), a, indices=True)
[[((0, 0), 1), ((0, 1), 2)], [((1, 0), 3), ((1, 1), 4)]]
Run Code Online (Sandbox Code Playgroud)

编辑

所以我们可以这样编写上面的add_matrices函数:

def add_matrices(a,b):
    return listmatrixMap(add, a, b)
Run Code Online (Sandbox Code Playgroud)

演示:

>>> add_matrices(c, d)
[[11, 4], [12, 6], [15, 19]]
Run Code Online (Sandbox Code Playgroud)

  • 我非常欣赏这项工作,但它比我的薪水高一点.我上周开始教自己如何编写"如何像计算机科学家一样思考"一书.但是看看这个网站在我阅读这本书的过程中如何继续进行谷歌搜索,我相信它会帮助那些比我更有见识的人.谢谢. (3认同)
  • @gergalerg:没问题,我很高兴解释为什么你的答案几乎是正确的.这非常重要:返回值和打印值之间存在差异.**一般来说,你*不想*在函数中调用`print`(或任何其他"副作用代码"); 你会希望函数返回*new*值,你可以*稍后*打印.**例如你的函数没有返回任何东西:`add_matrices(c,d)== None`.你想要`add_matrices(c,d)== [[..],[..],[..]]`.虽然所有这些答案看起来都不同,但它们*都*创建了一个**新**空白矩阵,填入并返回.=) (2认同)

Pet*_*nov 6

def addM(a, b):
    res = []
    for i in range(len(a)):
        row = []
        for j in range(len(a[0])):
            row.append(a[i][j]+b[i][j])
        res.append(row)
    return res
Run Code Online (Sandbox Code Playgroud)