Vince Jerald Villamora - 5 months ago 37
Python Question

# Pythonic way of copying a non-zero value list to fill in the zeroes of another list

I have a list

``````a = [2, 5, 6, 3, 9]
``````

here's what the other list should look like

``````b = [0, 7, 9, 3, 3, 0, 4, 0, 3, 1, 0, 0, 4]
``````

what I'm trying to achieve is to copy the first list in to the second list so it replaces the zeroes like so

``````c = [2, 7, 9, 3, 3, 5, 4, 6, 3, 1, 3, 9, 4]
``````

If there are too many zeroes in
`b`
, it will just be ignored and will stay 0 in
`c`
and if the there are too few zeroes in
`b`
, some values in a would simply not be carried over or copied to
`c`

edit

and is there a way to do this to fill a list like this

``````b = [[0, 3, 9, 1, 3]
[3, 3, 4, 2, 0]
[3, 5, 5, 0, 2]
[0, 0, 3, 8, 9]
[1, 2, 3, 4, 5]]
``````

so that
`c`
will be

``````c = [[2, 3, 9, 1, 3]
[3, 3, 4, 2, 5]
[3, 5, 5, 6, 2]
[3, 9, 3, 8, 9]
[1, 2, 3, 4, 5]]
``````

One way would be to use `iter` to create an object giving each element in `a` one-by-one, and then use an ordinary listcomp:

``````>>> a = [2, 5, 6, 3, 9]
>>> b = [0, 7, 9, 3, 3, 0, 4, 0, 3, 1, 0, 0, 4]
>>> fill = iter(a)
>>> c = [x if x != 0 else next(fill) for x in b]
>>> c
[2, 7, 9, 3, 3, 5, 4, 6, 3, 1, 3, 9, 4]
``````

As @bulbus notes, this will raise a StopIteration exception if you don't have enough zeros to fill. You could use the default value for `next`, e.g. `next(fill, 0)` if you want to avoid that.

For your 2D case, the same approach works, we just need to change the listcomp:

``````>>> fill = iter(a)
>>> b = [[0, 3, 9, 1, 3], [3, 3, 4, 2, 0], [3, 5, 5, 0, 2], [0, 0, 3, 8, 9], [1, 2, 3, 4, 5]]
>>> c = [[x if x != 0 else next(fill) for x in row] for row in b]
>>> c
[[2, 3, 9, 1, 3], [3, 3, 4, 2, 5], [3, 5, 5, 6, 2], [3, 9, 3, 8, 9], [1, 2, 3, 4, 5]]
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download