Python: 调整NumPy数组

我刚开始学习Python,感觉还不错,我甚至可以说Python非常性感,直到我需要移动一个4×4矩阵的内容,我打算用它来构建一个2048游戏的演示,游戏的演示在这里这里。我有这样一个函数:

def cover_left(matrix):        new=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]        for i in range(4):             count=0             for j in range(4):                if mat[i][j]!=0:                    new[i][count]=mat[i][j]                    count+=1        return new

如果你像这样调用这个函数,它会执行以下操作:

cover_left([              [1,0,2,0],               [3,0,4,0],               [5,0,6,0],               [0,7,0,8]          ])

它会将零移到左边,产生以下结果:

[  [1, 2, 0, 0],   [3, 4, 0, 0],   [5, 6, 0, 0],   [7, 8, 0, 0]]

请问有人能帮我用numpy的方式实现这个功能吗?我相信这样会更快,代码也会更少(我是在深度优先搜索算法中使用),更重要的是,实现cover_upcover_downcover_left的功能。

`cover_up`    [  [1, 7, 2, 8],       [3, 0, 4, 0],       [5, 0, 6, 0],       [0, 0, 0, 0]]`cover_down`    [  [0, 0, 0, 0],       [1, 0, 2, 0],       [3, 0, 4, 0],       [5, 7, 6, 8]]`cover_right`    [  [0, 0, 1, 2],       [0, 0, 3, 4],       [0, 0, 5, 6],       [0, 0, 7, 8]]

回答:

这里有一个受这篇文章启发的向量化方法,并推广到覆盖所有四个方向的非零值 –

def justify(a, invalid_val=0, axis=1, side='left'):        """    调整二维数组    参数    ----------    A : ndarray        输入数组,需要调整    axis : int        调整的轴    side : str        调整的方向。可以是'left', 'right', 'up', 'down'        对于axis=1,应该是'left'或'right',对于axis=0,应该是'up'或'down'。    """    if invalid_val is np.nan:        mask = ~np.isnan(a)    else:        mask = a!=invalid_val    justified_mask = np.sort(mask,axis=axis)    if (side=='up') | (side=='left'):        justified_mask = np.flip(justified_mask,axis=axis)    out = np.full(a.shape, invalid_val)     if axis==1:        out[justified_mask] = a[mask]    else:        out.T[justified_mask.T] = a.T[mask.T]    return out

示例运行 –

In [473]: a # 输入数组Out[473]: array([[1, 0, 2, 0],       [3, 0, 4, 0],       [5, 0, 6, 0],       [6, 7, 0, 8]])In [474]: justify(a, axis=0, side='up')Out[474]: array([[1, 7, 2, 8],       [3, 0, 4, 0],       [5, 0, 6, 0],       [6, 0, 0, 0]])In [475]: justify(a, axis=0, side='down')Out[475]: array([[1, 0, 0, 0],       [3, 0, 2, 0],       [5, 0, 4, 0],       [6, 7, 6, 8]])In [476]: justify(a, axis=1, side='left')Out[476]: array([[1, 2, 0, 0],       [3, 4, 0, 0],       [5, 6, 0, 0],       [6, 7, 8, 0]])In [477]: justify(a, axis=1, side='right')Out[477]: array([[0, 0, 1, 2],       [0, 0, 3, 4],       [0, 0, 5, 6],       [0, 6, 7, 8]])

通用情况(ndarray)

对于ndarray,我们可以修改为 –

def justify_nd(a, invalid_val, axis, side):        """    调整ndarray中有效元素(非invalid_val)。    参数    ----------    A : ndarray        输入数组,需要调整    invalid_val : scalar        无效值    axis : int        调整的轴    side : str        调整的方向。必须是'front'或'end'。        因此,使用'front'时,有效元素被推到前面,        使用'end'时,有效元素被推到指定轴的末尾。    """        pushax = lambda a: np.moveaxis(a, axis, -1)    if invalid_val is np.nan:        mask = ~np.isnan(a)    else:        mask = a!=invalid_val    justified_mask = np.sort(mask,axis=axis)        if side=='front':        justified_mask = np.flip(justified_mask,axis=axis)                out = np.full(a.shape, invalid_val)    if (axis==-1) or (axis==a.ndim-1):        out[justified_mask] = a[mask]    else:        pushax(out)[pushax(justified_mask)] = pushax(a)[pushax(mask)]    return out

示例运行 –

输入数组:

In [87]: aOut[87]: array([[[54, 57,  0, 77],        [77,  0,  0, 31],        [46,  0,  0, 98],        [98, 22, 68, 75]],       [[49,  0,  0, 98],        [ 0, 47,  0, 87],        [82, 19,  0, 90],        [79, 89, 57, 74]],       [[ 0,  0,  0,  0],        [29,  0,  0, 49],        [42, 75,  0, 67],        [42, 41, 84, 33]],       [[ 0,  0,  0, 38],        [44, 10,  0,  0],        [63,  0,  0,  0],        [89, 14,  0,  0]]])

'front',沿axis =0

In [88]: justify_nd(a, invalid_val=0, axis=0, side='front')Out[88]: array([[[54, 57,  0, 77],        [77, 47,  0, 31],        [46, 19,  0, 98],        [98, 22, 68, 75]],       [[49,  0,  0, 98],        [29, 10,  0, 87],        [82, 75,  0, 90],        [79, 89, 57, 74]],       [[ 0,  0,  0, 38],        [44,  0,  0, 49],        [42,  0,  0, 67],        [42, 41, 84, 33]],       [[ 0,  0,  0,  0],        [ 0,  0,  0,  0],        [63,  0,  0,  0],        [89, 14,  0,  0]]])

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注