仅使用 maps、lambda 和 reduce 查找 3D 矩阵中的非零条目

0 投票
3 回答
615 浏览
提问于 2025-04-18 15:18

我有一个三维的矩阵(也叫张量),可以通过以下方式访问:

m[x][y][z]

我想找到并保存这个矩阵中所有非零的元素,以及它们的位置索引。(因为这个矩阵是稀疏的,很多地方都是零)

所以,下面的代码可以实现这个功能:

for i, x in enumerate(m):
      if x:
         for j,y in enumerate(x):
            if y:
               for k,z in enumerate(y):
                 if z:
                   print i,j,k, z

我想用类似的方式,但只使用lambda表达式、map和reduce来实现这个效果。

3 个回答

1

这里有一个比较复杂的解决办法,主要是用到“映射”、“过滤”和“归约”这几个操作。首先,我们要用“映射”和“过滤”来创建一个新的矩阵,这个矩阵里只包含非零的值,并且还附上了它们的位置索引:

new_matrix = map(lambda (k,z):map(lambda (j,y):map(lambda (i,x):  [k,j,i,x], enumerate(filter( lambda val: val>0, y))), enumerate(z)), enumerate(m))

接下来,我们再对这个新矩阵进行“归约”操作:

non_zeros = reduce(lambda a,b: reduce(lambda c,d: c+d, a)+reduce(lambda c,d: c+d, b), new_matrix)
2

你可以使用numpy这个库。

import numpy as np
...
arr = np.arry(m)
non_zeros = np.transpose(np.nonzero(arr))

可以查看这个链接了解更多信息:http://docs.scipy.org/doc/numpy/reference/generated/numpy.nonzero.html

希望对你有帮助。

1

正如Pankaj Sharma提到的,numpy是Python中处理矩阵的最佳选择。

你也可以使用itertools这个工具:

from itertools import product

d3 = [[[0 for col in range(3)]for row in range(3)] for x in range(3)]

d3[0][2][2] = 1

for i, j, k in product(xrange(3), xrange(3), xrange(3)):
    if(d3[i][j][k]): print "%s %s %s = %s" % (i, j, k, d3[i][j][k])

输出结果:

0 2 2 = 1

如果你还是想用Lambda/Map/Reduce的话:

from __future__ import print_function  # we need print as function to use within lamdba
d3 = [[[0 for col in range(3)]for row in range(3)] for x in range(3)]

d3[0][2][2] = 1
d3[1][2][2] = 2

d3 = reduce(list.__add__, reduce(list.__add__, d3))  # get flatten matrix

map(lambda x: print(x[0]/9, (x[0] - (x[0]/9)*9)/3, x[0] % 3, '=', x[1]), [(i, e) for i, e in enumerate(d3) if e != 0])

#print x / 9             # i
#print (x - (x/9)*9) / 3 # j
#print x % 3             # k

输出结果:

0 2 2 = 1

1 2 2 = 2

撰写回答