给定一个矩阵,return 它所有成对邻居的列表(或生成器)

Given a matrix, return a list (or generator) of all it's pairwise-neighbors

假设我有这个矩阵:(不必平方)

a b c
d e f
g h i

我想要 return 一个包含所有成对邻居的列表或生成器。 含义:

[[a,b], [b,c], [d,e], [e,f], [g,h], [h,i], [a,d], [b,e], [c,f], [d,g], [e,h], [f,i]]

AND(!) 仅向 return 添加一个选项:a*b + b*c + d*e + e*f + g*h + ... + f*i

如果示例中的解释不够清楚,如果两个元素彼此相邻,从左到右或从下到上(不是对角线!)。

这是我目前所做的:

def neighbors(X, returnSet=False):
    '''
    :param X: The matrix
    :param returnSet:  False[DEFAULT] = Return sum of Xi*Xj (when Xi and Xj are pairwise-neighbors)
                       True = Return the set of all neighbors.
    :return: Depends on returnSet
    '''
    sum, neighbors = 0, []
    for i in range(0, X.shape[0]):
        for j in range(0, X.shape[1]):
            if j + 1 < X.shape[1]:
                neighbors.append([X[i][j], X[i][j + 1]]) if returnSet else None
                sum += X[i][j] * X[i][j + 1]
            if i + 1 < X.shape[0]:
                neighbors.append([X[i][j], X[i + 1][j]]) if returnSet else None
                sum += X[i][j] * X[i + 1][j]
    return neighbors if returnSet else sum

此代码有效,但我不太喜欢它的外观。你能想出比这更“酷”的算法吗?或者更有效率?我喜欢 python 代码简短。

与您的 基本相同,只是在两个轴上使用双点积(不是那么漂亮)。

a = np.arange(9).reshape(3,3)
np.einsum('ij, ij->', a[1:], a[:-1]) + np.einsum('ij, ij->', a[:, 1:], a[:, :-1])
Out[]: 232

neighbors(a)
Out[]: 232

如果你只想要一对:

h = np.stack([a[:, 1:], a[:, :-1]]).transpose(1,2,0).reshape(-1, 2)
v = np.stack([a[1:], a[:-1]]).transpose(1,2,0).reshape(-1, 2)
np.vstack([h, v])
Out[]: 
array([[1, 0],
       [2, 1],
       [4, 3],
       [5, 4],
       [7, 6],
       [8, 7],
       [3, 0],
       [4, 1],
       [5, 2],
       [6, 3],
       [7, 4],
       [8, 5]])