【问题标题】:Add two matrices in python在python中添加两个矩阵
【发布时间】:2011-06-17 07:33:38
【问题描述】:

我正在尝试编写一个添加两个矩阵以通过以下文档测试的函数:

  >>> 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]]

于是我写了一个函数:

def add(x, y):
    return x + y

然后我写了以下函数:

def add_matrices(c, d):
    for i in range(len(c)):
        print map(add, c[i], d[i])

排序得到了正确的答案。

【问题讨论】:

    标签: python nested-lists


    【解决方案1】:

    矩阵库

    您可以使用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]])
    

    本土解决方案:重量级

    假设您想自己实现它,您需要设置以下机制,它可以让您定义任意成对操作:

    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
    

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

        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)
    

    例子:

    >>> 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]]
    

    您甚至可以添加成对取幂、取反、二元运算等。我在这里不演示,因为矩阵乘法和矩阵求幂最好保留 * 和 **。


    本土解决方案:轻量级

    如果您只是想要一种非常简单的方法来仅将一个操作映射到两个嵌套列表矩阵,您可以这样做:

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

    演示:

    >>> listmatrixMap(operator.add, a, b, c))
    [[3, 4], [5, 6]]
    

    通过额外的 if-else 和关键字参数,您可以在 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)]]
    

    编辑

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

    def add_matrices(a,b):
        return listmatrixMap(add, a, b)
    

    演示:

    >>> add_matrices(c, d)
    [[11, 4], [12, 6], [15, 19]]
    

    【讨论】:

    • 我真的很感激这份工作,但它比我的薪水略高。上周,我刚刚从《如何像计算机科学家一样思考》一书中开始自学如何编程。但是看到这个网站在我阅读本书时如何不断出现在谷歌搜索中,我相信它会帮助比我更有知识的人。谢谢。
    • @gergalerg:没问题,我很高兴解释为什么你的答案几乎是正确的。这一点非常重要:返回值和打印值是有区别的。 一般来说,您确实想在函数中调用print(或任何其他“副作用代码”);您将希望函数返回 值,您可以稍后打印。 例如您的函数没有返回任何内容:add_matrices(c,d)==None。你想要add_matrices(c,d)==[[..],[..],[..]]。尽管所有这些答案看起来都不同,但它们all 创建了一个new 空白矩阵,将其填充并返回。 =)
    • @gergalerg:[需要更多空间] 这称为函数式编程,非常重要。无论如何,为了进一步说明对 doctest 的误解,在解释器中同时输入 1print(1) 将显示相同的结果。然而1==1 是True,而print(1)==1 是False(print(...) 的值是什么)。这里的寓意是我们必须从函数中返回一个值,否则我们以后将无法在其他函数中重用它们。在处理 doctest 时,您不需要调用 print,通常只需要在大型程序中调用一次(或从不调用)。
    【解决方案2】:
    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
    

    【讨论】:

      【解决方案3】:

      另一种解决方案:

      map(lambda i: map(lambda x,y: x + y, matr_a[i], matr_b[i]), xrange(len(matr_a)))
      

      【讨论】:

        【解决方案4】:
        from itertools import izip
        
        def add_matrices(c, d):
            return [[a+b for a, b in izip(row1, row2)] for row1, row2 in izip(c, d)]
        

        但是如上所述,没必要重新发明轮子,直接用numpy,可能会更快更灵活。

        【讨论】:

          猜你喜欢
          • 2018-07-25
          • 1970-01-01
          • 2021-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-09-22
          相关资源
          最近更新 更多