2

Is there any easy way to flatten

import numpy    
np.arange(12).reshape(3,4)
Out[]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

into

array([ 0,  1,  4,  5, 8, 9, 2, 3, 6, 7, 10, 11])
Divakar
  • 218,885
  • 19
  • 262
  • 358
cass
  • 309
  • 1
  • 5
  • 14
  • 1
    `arr.reshape(3, 2, 2).swapaxes(0, 1).ravel()` will do, but without the expected logic, it is hard to say if it is what you are after... – norok2 Sep 25 '19 at 15:13

6 Answers6

3

It seems like you are looking to consider a specific number of cols to form blocks and then getting the elements in each block and then moving onto the next ones. So, with that in mind, here's one way -

In [148]: a
Out[148]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

In [149]: ncols = 2 # no. of cols to be considered for each block

In [150]: a.reshape(a.shape[0],-1,ncols).swapaxes(0,1).ravel()
Out[150]: array([ 0,  1,  4,  5,  8,  9,  2,  3,  6,  7, 10, 11])

The motivation behind is discussed in detail in this post.

Additionally, to keep the 2D format -

In [27]: a.reshape(a.shape[0],-1,ncols).swapaxes(0,1).reshape(-1,ncols)
Out[27]: 
array([[ 0,  1],
       [ 4,  5],
       [ 8,  9],
       [ 2,  3],
       [ 6,  7],
       [10, 11]])

And to have it in a intuitive 3D array format -

In [28]: a.reshape(a.shape[0],-1,ncols).swapaxes(0,1)
Out[28]: 
array([[[ 0,  1],
        [ 4,  5],
        [ 8,  9]],

       [[ 2,  3],
        [ 6,  7],
        [10, 11]]])
Divakar
  • 218,885
  • 19
  • 262
  • 358
2

For this I'd simply slice and concatenate:

n = a.shape[1]//2
np.concatenate([a[:,:n], a[:,n:]]).ravel()
# array([ 0,  1,  4,  5,  8,  9,  2,  3,  6,  7, 10, 11])
yatu
  • 86,083
  • 12
  • 84
  • 139
0

You can use a list comprehension to slice the array into blocks and then use the numpy.ndarray.flatten method to flatten the blocks into a 1D array (this will only work if a.shape[1] is divisible by the block size n):

import numpy as np

a = np.arange(12).reshape(3, 4)

n = 2

res = np.array([a[:, i : i + n] for i in range(0, a.shape[1], n)]).flatten()

print(res)

Output:

[ 0  1  4  5  8  9  2  3  6  7 10 11 ]
DjaouadNM
  • 22,013
  • 4
  • 33
  • 55
0

Another way:

first_list = [entry[0:2] for entry in a]
second_list = [entry[2:4] for entry in a]
flat_list = [item for sublist in first_list for item in sublist] + [item for sublist in second_list for item in sublist]

flat_list # [0, 1, 4, 5, 8, 9, 2, 3, 6, 7, 10, 11]
Carsten
  • 2,765
  • 1
  • 13
  • 28
0

I have a solution that doesn't involve numpy if you want, and it will take care for every kind of array you'll get,

[[12312],[],[[]]] 
[[[2]], [4, [5, 6, [6], 6, 6, 6], 7]]
[-1, [1, [-2], 1], -1]
etc

First option(won't work for strings)

def flat_list(array):
    return list(flatten(array))              
def flatten(nested): 
    try:
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested

Second option:

def flatten(nested): #in case you got strings and you want to avoide an infinite recursion
    try:
        # Don't iterate over string-like objects:
        try: nested + ''
        except TypeError: pass
        else: raise TypeError
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested
eladgl
  • 69
  • 8
0

You are using numpy here. It has a method to do exactly what you want.

import numpy as np

arr = np.arange(12).reshape(3,4)
flat = arr.flatten()

Another approach:

a = []
[a.extend(x) for x in arr]