Search code examples
pythonlistfill

How to make a fill down like process in list of lists?


I have the following list a with None values for which I want to make a "fill down".

a = [
        ['A','B','C','D'],
        [None,None,2,None],
        [None,1,None,None],
        [None,None,8,None],
        ['W','R',5,'Q'],
        ['H','S','X','V'],
        [None,None,None,7]
    ]

The expected output would be like this:

b = [
        ['A','B','C','D'],
        ['A','B',2,'D'],
        ['A',1,'C','D'],
        ['A','B',8,'D'],
        ['W','R',5,'Q'],
        ['H','S','X','V'],
        ['H','S','X',7]
    ]

I was able to make the next code and seems to work but I was wondering if there is a built-in method or more direct way to do it. I know that there is something like that using pandas but needs to convert to dataframe, and I want to continue working with list, if possible only update a list, and if not possible to modify a then get output in b list. Thanks

b = []
for z in a:
    if None in z:
        b.append([temp[i] if value == None else value for i, value in enumerate(z) ])
    else:
        b.append(z)
        temp = z

Solution

  • You could use a list comprehension for this, but I'm not sure it adds a lot to your solution already.

    b = [a[0]]
    for a_row in a[1:]:
        b.append([i if i else j for i,j in zip(a_row, b[-1])])
    

    I'm not sure if it's by design, but in your example a number is never carried down to the next row. If you wanted to ensure that only letters are carried down, this could be added by keeping track of the letters last seen in each position. Assuming that the first row of a is always letters then;

    last_seen_letters = a[0]
    b = []
    for a_row in a:
        b.append(b_row := [i if i else j for i,j in zip(a_row, last_seen_letters)])
        last_seen_letters = [i if isinstance(i, str) else j for i,j in zip(b_row, last_seen_letters)]