如何使用2D numpy数组中的逻辑条件从/向3D列表中精确/赋值

时间:2017-06-09 21:46:30

标签: python arrays numpy

我被一个关于python列表的值分配/提取问题阻止了。 我有一个存储在numpy数组中的连接矩阵:

conn = np.array([[0, 1, 0], [1, 0, 3], [0, 3, 0]])

接下来我想要实现的是:首先,创建一个3D列表path,其中第i个,第j个元素被设置为长度为conn[i, j]的列表。 为了说明,

path = [ [[] for kk in range(3)] for k in range(3)]
(idx_x, idx_y) = np.nonzero(conn)
non_zero_values = conn[np.nonzero(conn)]
for iter in range(len(non_zero_values)):
    path[idx_x[iter]][idx_y[iter]] = [0 for k in range(non_zero_values[iter])]

其次,删除path的第i个,第j个位置的列表的最后一个值

exit_matrix = np.zeros((3, 3))    
for iter in range(len(non_zero_values)):
    exit_matrix[idx_x[iter], idx_y[iter]] = path[idx_x[iter]][idx_y[iter]].pop()

第三,在path的第i个第j个位置的列表开头插入一个值:

enter_matrix = np.array([[0, 4, 0], [2, 0, 1], [0, 3, 0]])
for iter in range(len(non_zero_values)):
    path[idx_x[iter]][idx_y[iter]].insert(0, enter_matrix[idx_x[iter], idx_y[iter]])

有没有有效的方法来实现这一目标?你的任何建议都不仅仅是欣赏它。我是python的新手。

非常感谢您抽出时间阅读我的问题。

1 个答案:

答案 0 :(得分:0)

zip可以替换您的iter循环,并使其更易于阅读(但可能不会更快):

for iter in range(len(non_zero_values)):
    path[idx_x[iter]][idx_y[iter]] = [0 for k in range(non_zero_values[iter])]

for i,j,v in zip(idx_x, idx_y, non_zero_values):
    path[i][j] = [0 for k in range(v)]
In [516]: conn = np.array([[0, 1, 0], [1, 0, 3], [0, 3, 0]])
In [517]: path = [ [[] for kk in range(3)] for k in range(3)]
     ...: (idx_x, idx_y) = np.nonzero(conn)
     ...: non_zero_values = conn[np.nonzero(conn)]
     ...: 
In [518]: for i,j,v in zip(idx_x, idx_y, non_zero_values):
     ...:     path[i][j] = [0 for k in range(v)]
     ...:     
In [519]: path
Out[519]: [[[], [0], []], [[0], [], [0, 0, 0]], [[], [0, 0, 0], []]]

这些内部列表的可变长度强烈表明我们无法避免列表迭代。可变长度与矩形多维数组不能很好地融合。

我要考虑的另一件事是定义一个函数来合并每个i,j对的动作。也就是说,在一个循环中进行初始化,弹出和插入。快速浏览表明一个i,j对的操作对于另一对的操作是独立的。