pythonarraysnumpy

How to get all array edges?


I have a n x n array, and want to receive its outline values. For example,

[4,5,6,7]

[2,2,6,3]

[4,4,9,4]

[8,1,6,1]

from this, i would get this

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

(see where bold)

So essentially, what is the most efficient way of getting a 1D array of all the values going around the edges of a 2D array? I ask because I assume there is a numPy function that helps with this (which I haven't yet found!), instead of doing it manually with loops?


Solution

  • In [1]: arr=np.arange(16).reshape(4,4)
    In [2]: arr
    Out[2]: 
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11],
           [12, 13, 14, 15]])
    

    A relatively straight forward way of doing this - in clockwise order is:

    In [5]: alist=[arr[0,:-1], arr[:-1,-1], arr[-1,::-1], arr[-2:0:-1,0]]
    In [6]: alist
    Out[6]: [array([0, 1, 2]), array([ 3,  7, 11]), array([15, 14, 13, 12]), array([8, 4])]
    In [7]: np.concatenate(alist)
    Out[7]: array([ 0,  1,  2,  3,  7, 11, 15, 14, 13, 12,  8,  4])
    

    In a sense it's a loop, in that I have to build 4 slices. But if 4 is small compared to n, that's a small price. It has to concatenate at some level.

    If order doesn't matter we could simplify the slices some (e.g. forgetting the reverse order, etc).

    alist=[arr[0,:], arr[1:,-1], arr[-1,:-1], arr[1:-1,0]]
    

    If I didn't care about order, or double counting the corners I could use:

    np.array([arr[[0,n],:], arr[:,[0,n]].T]).ravel()
    

    eliminating the duplicate corners

    In [18]: np.concatenate((arr[[0,n],:].ravel(), arr[1:-1,[0,n]].ravel()))
    Out[18]: array([ 0,  1,  2,  3, 12, 13, 14, 15,  4,  7,  8, 11])