Iterate and sum elements of second list based on sequences in another list

Viewed 37

I have two lists

l1 = [0,1,2,2,0,1,1,0]
l2 = [(0,2),(3,5),(6,8),(9,10),(11,15),(16,18),(19,20),(21,22)]

If there is a sequence of 1s and 2s in the first list, followed by 1 or 0, then I want it to return the first element of the tuple in the corresponding index in the second list and the second element of the tuple of the final 2. Same if it is just 1, followed by o or 1.

So the output here should be

out = [(3,10),(16,18),(19,20)]

This is what I have

for index, item in enumerate(true):
    if item == 0:
        continue
    elif item == 1 or item == 2:
        if true[index+1] == 0 or true[index+1] == 1:
            out.append(offsets[index])
        elif true[index+1] == 2:
            out.append((offsets[index][0], offsets[index+1][1]))

which results in

[(3, 8), (6, 10), (9, 10), (16, 18), (19, 20)]

Is there a more pythonic (and correct) way of approaching this?

1 Answers

The less indexes you're going to use, the better

First list is a sequential access list. I'd iterate on it. Second list is a random access list. You need indexes computed from the first list sequences to extract data

My proposal:

l1 = [0,1,2,2,0,1,1,0]
l2 = [(0,2),(3,5),(6,8),(9,10),(11,15),(16,18),(19,20),(21,22)]

# adding 0 handles the case where l1 doesn't end with 0
it = enumerate(l1+[0])

result = []

sv = 0
try:
    while True:
        if sv==1:
            fi,fv = si,sv
        else:
            while True:
                fi,fv = next(it)
                if fv:
                    break
        while True:
            si,sv = next(it)
            if sv == 0 or sv == 1:
                break
        result.append((l2[fi][0],l2[si-1][1]))
except StopIteration:
    pass

print(result)

output:

[(3, 10), (16, 18), (19, 20)]

I chose to manually iterate on the first list by creating an iterator out of the enumerate expression (which is already okay since enumerate is already an iterator). That way, I can iterate manually on the first index, then on the second index using inner while True loops and next, break when found.

And if the second value is a 1, it stops the sequence but also needs to be reinjected in the iteration for next first value. It's not possible to do that with iterators, hence the test of previous sv and si values to avoid missing the third sequence.

Related