代码之家  ›  专栏  ›  技术社区  ›  user1179317

在numpy中使用wrap的索引的最佳方法

  •  1
  • user1179317  · 技术社区  · 6 年前

    假设我在下面有一个二维数组:

     [[ 0 0 0 0 0 0 ]
      [ 0 0 0 0 0 0 ]
      [ 0 0 0 0 0 0 ]
      [ 0 0 0 0 0 2 ]
      [ 0 1 0 0 0 0 ]
      [ 0 0 0 0 0 0 ]]
    

    我想知道从'1'(索引4,1)到'2'(索引3,5)的方向。假设方向只有上,下,左,右。因此没有对角线运动。

    一种获得方向的方法:

    "right" if destination.x > start.x else "left" if target.x < start.x else None
    
    "down" if destination.y > start.y else "up" if destination.y < start.y else None
    

    所以在这个例子中,我们可以通过“向上”或“向右”进入“2”或目的地。当然,这只是一个步骤,一旦你移动,可以执行相同的逻辑,以更接近目的地。

    这个逻辑的问题是它没有考虑包装。按照这个逻辑,到达目的地需要5个步骤。有一个更短的方式,实际上走左边或向上,可以到达目的地,只需3步,因为包装。

    正在考虑生成另一个数组,其中开始将是数组的中间,并执行相同的逻辑。问题是如果数组是偶数的(比如这是6x6,需要填充才能得到中间值。例如:

     [[ 0 0 0 0 0 0 0]
      [ 0 0 0 0 0 0 0]
      [ 0 2 0 0 0 0 0]
      [ 0 0 0 1 0 0 0]
      [ 0 0 0 0 0 0 0]
      [ 0 0 0 0 0 0 0]
      [ 0 0 0 0 0 0 0]]
    

    这里的阵列现在是7x7。我相信没有这个额外的步骤有一个更简单的方法来得到答案,但是我想不起来。

    3 回复  |  直到 6 年前
        1
  •  0
  •   iGian    6 年前

    你能考虑用这种方法吗?

    import numpy as np
    
    # build the array
    a = np.zeros( (6,6), dtype=int )
    a[4][1] = 1
    a[3][5] = 2
    
    # extract required informations
    i,j = np.where(a == 1)
    h,k =np.where(a == 2)
    
    print (i-h) => [1]
    print (j-k) => [-4]
    
        2
  •  0
  •   Andreas K.    6 年前

    在周期边界条件下,有一个很简单的计算距离的公式。下面我只考虑x轴上的周期性b.c.:

    import numpy as np
    
    # periodic boundary condition for the x-axis only
    def steps(start, dest, L_x):
        x_start = start[1]
        y_start = start[0]
        x_dest = dest[1]
        y_dest = dest[0]
    
        dx = x_dest - x_start
        if np.abs(dx) <= L_x/2:
            steps_x = x_dest - x_start
        else:
            if dx > 0:
                steps_x = (x_dest - L_x) - x_start
            else:
                steps_x = (x_dest + L_x) - x_start            
    
        steps_y = y_dest - y_start
    
        return steps_x, steps_y
    

    例子:

    grid = np.array([[0, 0, 0, 0, 0, 0 ],
                     [0, 0, 0, 0, 0, 0 ],
                     [0, 0, 0, 0, 0, 0 ],
                     [0, 0, 0, 0, 0, 2 ],
                     [0, 1, 0, 0, 0, 0 ],
                     [0, 0, 0, 0, 0, 0 ]])
    
    L_x = grid.shape[1]    
    start = (4, 1)  # (y, x) or (i, j)
    dest = (3, 5)
    
    steps_x, steps_y = steps(start, dest, grid)
    dir_x = 'left' if steps_x < 0 else 'right'
    dir_y = 'up' if steps_y < 0 else 'down'
    print(abs(steps_x), dir_x, ',', abs(steps_y), dir_y)
    
    Out: 2 left , 1 up
    
        3
  •  0
  •   B. M.    6 年前

    我尝试另一种方法:

    在水平长度轴上 size ,从 a b delta = ((b-a)%size*2-1)//size

    • 如果 delta=-1 , a=b :你不动。
    • 如果 delta=0 :你必须向右走。
    • 如果 delta=1 :你必须向左走。

    所以这段代码似乎有效

    size=10
    vertical=['down','up',None]
    horizontal=['right','left',None]
    
    def side(a,b):
        return ((b-a)%size*2-1)//size
    
    def step(M1,M2):
        x1,y1=M1
        x2,y2=M2
        return (vertical[side(x1,x2)],horizontal[side(y1,y2)])
    

    例如:

    In [6]: step((2,1),(2,8))
    Out[6]: (None, 'left')