15

次のドキュメントテストに合格するために2つの行列を追加する関数を作成しようとしています:

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

そして、私正しい答えを得ることができます。

4

4 に答える 4

23

行列ライブラリ

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

対累乗、否定、二項演算などを追加することもできます。行列の乗算と行列のべき乗のために * と ** を残すのがおそらく最善であるため、ここでは説明しません。


自家製のソリューション: 軽量

操作を 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 とキーワード引数を使用すると、ラムダでインデックスを使用できます。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]]
于 2011-06-17T07:34:48.657 に答える
7
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
于 2011-06-17T07:42:39.557 に答える
4

もう1つの解決策:

map(lambda i: map(lambda x,y: x + y, matr_a[i], matr_b[i]), xrange(len(matr_a)))
于 2011-06-17T07:53:42.400 に答える
3
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で、より速く、より柔軟になる可能性があります。

于 2011-06-17T07:52:02.873 に答える