高效地索引二维数组中的位置列表

时间:2019-11-29 17:56:05

标签: python numpy numpy-ndarray numpy-slicing

此函数需要一些tictactoe板并返回合法尝试的动作(-1代表“ O”,1代表“ X”,0代表空白)

def legal_locations(boards, moves):

    legal_idxs, legal_locs = [], []
    illegal_idxs, illegal_locs = [], []

    for i, j in enumerate(moves):

        # The middle index here is 0 because the locations > 0 are reserved for historical states.
        # We only want to examine the current board state.
        if boards[i][0][j]:  # This location is occupied
            illegal_idxs.append(i)
            illegal_locs.append(j)

        else:  # unoccupied
            legal_idxs.append(i)
            legal_locs.append(j)

    return (legal_idxs, legal_locs), (illegal_idxs, illegal_locs)

它工作正常,但是“木板”只是一个矩形的numpy数组,而“运动”是一个列表。我认为必须有一种更快的方法来使用numpy完成此操作。有什么想法吗?

如果不能提高效率-最好知道这个问题会导致难以优化。

编辑:

boards =
array([[[ 0,  1,  0, -1,  0,  0,  0, -1,  0],
        [ 0,  1,  0,  0,  0,  0,  0, -1,  0],
        [ 0,  0,  0,  0,  0,  0,  0, -1,  0],
        [ 0,  0,  0,  0,  0,  0,  0,  0,  0]],

       [[ 0,  0,  0,  1, -1,  0,  0,  0, -1],
        [ 0,  0,  0,  1, -1,  0,  0,  0,  0],
        [ 0,  0,  0,  0, -1,  0,  0,  0,  0],
        [ 0,  0,  0,  0,  0,  0,  0,  0,  0]]])

此棋盘阵列显示两个游戏,每个游戏都有4个历史状态。

moves =
       [2, 8]

此移动数组显示两个索引。 因此,感兴趣的位置是:

boards[0][0][2]
boards[1][0][8]

因此,在此示例中,我们将从fxn获得以下收益:

([0], [2]), ([1], [8])

EDIT2:一个更核心的示例:

@AlexanderCécile我认为部分问题是我不知道如何使用列表作为索引。例如,我不知道如何减少该循环...

for i in range(legal.shape[0]):
  legal[i, 0, index_list[i]] = -1

其中len(index_list)== len(法律)

如果我能做到这一点,那么其他所有内容都应该使用np.nonzero固定到位

1 个答案:

答案 0 :(得分:1)

将数组转换为bool,然后使用np.where生成与True值相对应的索引(~运算符将转换转换数组)。对于单板:

array = np.array([[1, 0, 0], [-1, 1, 0], [1, -1, -1]])
mask = array.astype(bool)
illegal_row, illegal_col = np.where(mask)
legal_row, legal_col = np.where(~mask)

可以通过运行领先索引将其扩展到多个板。