Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace None in list with leftmost non none value

Tags:

python

Given

a = [None,1,2,3,None,4,None,None]

I'd like

a = [None,1,2,3,3,4,4,4]

Currently I have brute forced it with:

def replaceNoneWithLeftmost(val):
    last = None
    ret = []
    for x in val:
        if x is not None:
            ret.append(x)
            last = x
        else:
           ret.append(last)
    return ret

Finally, I'd like to get to

a = [1,1,2,3,3,4,4,4]

by running this right to left. Currently I have

def replaceNoneWithRightmost(val):
    return replaceNoneWithLeftmost(val[::-1])[::-1]

I'm not fussy about inplace or create a new list, but right now this smells to me. I can't see a way to store a temporary 'last' value and use map/lambda, and nothing else is coming to mind.

like image 938
tlrrd Avatar asked Jul 06 '15 21:07

tlrrd


2 Answers

IIUC, you could use itertools.accumulate to generate a forward fill:

>>> from itertools import accumulate
>>> a = [None,1,2,3,None,4,None,None]
>>> list(accumulate(a, lambda x,y: y if y is not None else x))
[None, 1, 2, 3, 3, 4, 4, 4]
like image 76
DSM Avatar answered Nov 10 '22 22:11

DSM


a = [None,1,2,3,None,4,None,None]

start = next(ele for ele in a if ele is not None)
for ind, ele in enumerate(a):
    if ele is None:
        a[ind] = start
    else:
        start = ele
print(a)
[1, 1, 2, 3, 3, 4, 4, 4]

You also only need to set start to a value if the first element is None:

if a[0] is None:
   start = next(ele for ele in a if ele is not None)
for ind, ele in enumerate(a):
    if ele is None:
        a[ind] = start
    else:
        start = ele
print(a)
like image 3
Padraic Cunningham Avatar answered Nov 10 '22 23:11

Padraic Cunningham