flattening of a numpy array along columns, in the order: lower triangle, diagonal, upper triangle

Here is a problem I'm trying to solve. Let's say we've a square array:

``````In [10]: arr
Out[10]:
array([[ 1,  2,  3,  4],
[ 5,  6,  7,  8],
[ 9, 10, 11, 12],
[13, 14, 15, 16]])
``````

What I'd like to have is to flatten this array in a specific order: first I want to flatten the lower triangle along axis-0 and then pick the diagonal, and finally flatten the upper triangle again along axis-0, which would finally give the flattened array as:

``````#              | lower triangle     |diag.elements| upper triangle  |
res = np.array([5, 9, 13, 10, 14, 15, 1, 6, 11, 16, 2, 3, 7, 4, 8, 12])
``````

Here is my partial solution so far, which doesn't give desired result yet.

``````In [16]: arr[np.tril(arr, k=-1) != 0]
Out[16]: array([ 5,  9, 10, 13, 14, 15])   # not correct!

In [17]: np.diag(arr)
Out[17]: array([ 1,  6, 11, 16])

In [18]: arr[np.triu(arr, k=1) != 0]
Out[18]: array([ 2,  3,  4,  7,  8, 12])  # not correct!
``````

Finally, to concatenate these 3 intermediate results. How to correctly index to obtain desired result? Alternatively, are there other ways of solving this problem?

On Best Solutions

Here's one based on `masking` and `concatenating/stacking` -

``````In [50]: r = np.arange(len(arr))

Out[54]: array([ 5,  9, 13, 10, 14, 15,  1,  6, 11, 16,  2,  3,  7,  4,  8, 12])
``````

Another based solely on `masking` -

``````n = len(arr)
r = np.arange(n)
``````
On

Use the transpose:

``````lower = np.tril(a, -1).T.ravel()
diag = np.diag(a)
upper = np.triu(a, 1).T.ravel()

result = np.concatenate([lower[lower != 0], diag, upper[upper != 0]])

print(result)
``````

Output:

``````[ 5  9 13 10 14 15  1  6 11 16  2  3  7  4  8 12]
``````
On

I am using index to select (`numpy` broadcast)

``````ary=ary.T

i,c=ary.shape
x=np.arange(i)
y=np.arange(c)
np.concatenate([ary[x[:,None]<y],ary[x[:,None]==y],ary[x[:,None]>y]])
Out[1065]: array([ 5,  9, 13, 10, 14, 15,  1,  6, 11, 16,  2,  3,  7,  4,  8, 12])
``````