Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python list traversal with gaps

Tags:

python

Hi I have a multidimensional list such as:

my_list = [[1,2,3,1,2],[1,0,3,1,2],[1,0,0,0,2],[1,0,3,0,2]]

where 0 represents a gap between two pieces of data.

What I need to do is iterate through the list and keep track of how many gaps are in each sublist and throw away the zeros. I think the best way is to break each sublist into chunks where there are zeros so I end up with smaller lists of integers and a number of gaps. Ideally, to form a new list which tells me the length of each chunk and number of gaps (i.e. chunks -1), such as:

new_list = [[5, 0], [[1, 3], 1], [[1, 1], 1], [[1, 1, 1], 2]]

or probably better:

new_list = [[5], [1, 3], [1, 1], [1, 1, 1]]

and I will know that the gaps are equal to len(chunk).

EDIT: However, leading and trailing zeros do not represent gaps. i.e. [0,0,1,2] represents one continuous chunk.

Any help much appreciated.

like image 815
Darwin Tech Avatar asked Jul 08 '26 06:07

Darwin Tech


2 Answers

itertools.groupby() is perfect for this:

from itertools import groupby
my_list = [[1,2,3,1,2],[1,0,3,1,2],[1,0,0,0,2],[1,0,3,0,2]]
new_list = [[len(list(g)) for k, g in groupby(inner, bool) if k] for inner in my_list]

Result:

>>> new_list
[[5], [1, 3], [1, 1], [1, 1, 1]]

The result contains the length of each non-zero chunk for each sublist, so for example [1,0,3,1,2] gives [1,3], so there are two chunks (one gap). This matches your second output format.

like image 106
Andrew Clark Avatar answered Jul 09 '26 21:07

Andrew Clark


Here is my humble code without any imports:

The algorithm is slightly long:

def toggle(n):
    return n != 0



def chunk_counter(L):
    """
    list -> list
    """

    chunk_list = []
    pivots = []
    for j in range(len(L)):
        if j == 0 and toggle(L[0]):
            pivots.append(j)
        elif toggle(L[j]) and toggle(L[j]) != toggle(L[j-1]):
            pivots.append(j)

    for m in range(len(pivots)):
        k = 0
        if m == len(pivots)-1:
            bound = len(L)
        else:
            bound = pivots[m+1]

        p = 0
        while p in range(bound - pivots[m]):
            if toggle(L[pivots[m] + p]):
                    k += 1
                    p += 1
            else:
                p += 1
        chunk_list.append(k)

    return chunk_list        


    def chunks(L):
    """
    (list of lists) -> list of lists
    """

    new_list = []
    for i in range(len(L)):
        new_list.append(chunk_counter(L[i]))

    return new_list

So, you may try the function chunks() on your list:

>>> L = [[1,2,3,1,2],[1,0,3,1,2],[1,0,0,0,2],[1,0,3,0,2], [0,0,1,2]]
>>> chunks(L)
[[5], [1, 3], [1, 1], [1, 1, 1], [2]]

Here's a recursive definition (a replacement for Chunk Counter):

    counter_list = []
def counter(L):
    k = 0
    while(k < len(L) and L[k] != 0):
        k +=1
    counter_list.append(k)
    if k == len(L):
        print counter_list
    else:
    counter(L[k+1:])
like image 24
kan Avatar answered Jul 09 '26 21:07

kan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!