How to recursively call a function in python to drop every element in a list to the bottom?

Viewed 146

For example, if my original nested list is :

[[' ', 'Y', ' ', 'X'], 
 ['S', ' ', 'V', ' '],
 ['T', 'X', 'Y', 'S'], 
 ['X', ' ', 'X', 'Y']]

I would like the result to be:

[[' ', ' ', ' ', ' '], 
 ['S', ' ', 'V', 'X'], 
 ['T', 'Y', 'Y', 'S'], 
 ['X', 'X', 'X', 'Y']]

So basically drop all the letters to the bottom without getting rid of any of the spaces and maintaining the structure of the list.

Here is what I have so far. My result gives me this which is incorrect.

[[' ', ' ', ' ', ' '],
 ['S', 'Y', 'V', 'X'],
 ['T', ' ', 'Y', 'S'],
 ['X', 'X', 'X', 'Y']]
def find_letters(m,constant):

    try:

        for i in range(len(m[constant])):
            if m[constant][i] == ' ':

                if m[constant - 1][i] != ' ':
                    m[constant][i] = m[constant - 1][i]
                    m[constant - 1][i] = ' '

        find_letters(m,constant - 1)   

    except IndexError:

        pass  



l = [[' ', 'Y', ' ', 'X'],
     ['S', ' ', 'V', ' '],
     ['T', 'X', 'Y', 'S'],
     ['X', ' ', 'X', 'Y']]
constant = -1   

(find_letters(l,constant))
2 Answers

You can try this.

You need to push all ' ''s upwards in each column and rest all other characters downwards maintaining order. You can use sorted() here.

a=[[' ', 'Y', ' ', 'X'],
   ['S', ' ', 'V', ' '],
   ['T', 'X', 'Y', 'S'],
   ['X', ' ', 'X', 'Y']]

out=list(zip(*[sorted(lst,key=lambda x: x==' ',reverse=True) for lst in zip(*a)]))
''' [(' ', ' ', ' ', ' '),
   ('S', ' ', 'V', 'X'),
   ('T', 'Y', 'Y', 'S'),
   ('X', 'X', 'X', 'Y')]'''

to operate more simple over the columns you could use np.arrays with np.apply_along_axis function:

m = np.array([[' ', 'Y', ' ', 'X'], 
 ['S', ' ', 'V', ' '],
 ['T', 'X', 'Y', 'S'], 
 ['X', ' ', 'X', 'Y']])

np.apply_along_axis(lambda c: [' '] *  list(c).count(' ') + [e for e in c if e != ' '],0 ,m)

output:

array([[' ', ' ', ' ', ' '],
       ['S', ' ', 'V', 'X'],
       ['T', 'Y', 'Y', 'S'],
       ['X', 'X', 'X', 'Y']], dtype='<U1')

if you want python list of lists you can use ndarray.tolist() function:

np.apply_along_axis(lambda c: [' '] *  list(c).count(' ') + [e for e in c if e != ' '],0 ,m).tolist()

output:

[[' ', ' ', ' ', ' '],
 ['S', ' ', 'V', 'X'],
 ['T', 'Y', 'Y', 'S'],
 ['X', 'X', 'X', 'Y']]
Related