Search code examples
pythonlistzerosub-array

select subarrays delimited by zeros in python


Given a list like:

A = [18, 7, 0, 0, 0, 9, 12, 0, 0, 11, 2, 3, 3, 0, 0, 7, 8]

is there a simple way to create subarrays, with those elements that are separated by zeros (or at least by NaNs)? I mean, like:

A1 = [18, 7]
A2 = [9, 12]
A3 = [11, 2, 3, 3]
A4 = [7, 8]

I've written:

q=0
for i in range(0,len(A)):
    if A[i]-A[i-1] < 1:
        q=q+1

to retrieve the number of zeros-packets present in the list. But I need to populate subarrays, as long as I encounter them through the list... maybe something with the split function? Thank you in advance.


Solution

  • Well, itertools has the solution for you: groupby(list, filter).

    If you want to group by zeroes, start with doing:

    B = itertools.groupby(A, lambda x:x == 0)
    

    The lambda expression "decides" which of the values should be a separator. You could separate by Nones using lambda x: x == None (for example). That will return you an iterable object. So, using a list comprehension, let's iterate through it (every iteration gives us a 2 values tuple):

    C = [(i, list(j)) for i, j in B] # j is cast to a list because it's originally an object, not a list.
    

    Output will be something like:

    [(False, [18, 7]), (True, [0]), (True, [0]), (True, [0]), ... ]

    Now, every list j that is the separator has a value True for i. So we can filter it:

    C = [list(j) for i, j in B if not i]
    

    Now, the result is a 2d list:

    [[18, 7], [9, 12], [11, 2, 3, 3], [7, 8]]

    So a one liner function:

    def splitArr():
        return [list(j) for i, j in itertools.groupby(A, lambda x:x == 0) if not i]