Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python - zip (skip over an element from one list but not from other)

Tags:

python

I've 2 list, a and b. Lets say len(a) = len(b) + 1. I want to iterate over both the list simultaneously, with a condition. Since, a has extra garbage value, it should skip that value from a, but it shouldnt skip the value from b. Then when next iteration happen, a should start from next element and b front the same initial element.

Explaination in the example.

a = [1,2,3,4,5,6,19,20]
b = [7,8,9,10,11,17,18]

for x,y in zip(a,b):
    if x == 5: # some condition
        #in this case y is 11
        continue # skip the value 5 from a but dont skip 11 from b.
    print x,y

The expected output will be

1 7
2 8
3 9
4 10
6 11 # 5 skipped because of some condition, but 11 remains intact
19 17
20 18

How can I do it?

OR if theres any other solution,while iterating simultaneously, please let me know.

like image 760
PythonEnthusiast Avatar asked Mar 17 '23 15:03

PythonEnthusiast


2 Answers

If you don't know which value you want to skip until you're already in the loop, you can use iterators, and call next to discard a value:

import itertools

a = [1,2,3,4,5,6,19,20]
b = [7,8,9,10,11,17,18]

it_a = iter(a)
it_b = iter(b)

for x,y in itertools.izip(it_a, it_b):
    if x == 5:
        x = next(it_a)
    print x,y

Which gives:

1 7
2 8
3 9
4 10
6 11
19 17
20 18

Be careful, though. If you call next(it_a), and you've read all of the values from a's iterator, you'll get a StopIteration exception, and you'll probably want to handle that somehow. Also, note that if you somehow skip two elements of a, then a will run out of elements before b, and zip will silently stop before producing the last element of b.

Alternatively, if you do know what you'd like to exclude before entering the for-loop, you can do essentially what @wnnmaw suggests below, but with a generator comprehension rather than a list comprehension. This will do the exclusion lazily:

a = [1,2,3,4,5,6,19,20]
b = [7,8,9,10,11,17,18]

it_a = (x for x in a if x not in {5, 42, 101})

for x,y in zip(it_a, b):
    print x,y
like image 151
jme Avatar answered Apr 08 '23 15:04

jme


I think the easiest way to do this is to simply cut out the "garbage" before zipping

>>> a = [1,2,3,4,5,6,19,20]
>>> b = [7,8,9,10,11,17,18]
>>> a.remove(5)
>>> a
[1, 2, 3, 4, 6, 19, 20]
>>> zip(a,b)
[(1, 7), (2, 8), (3, 9), (4, 10), (6, 11), (19, 17), (20, 18)]
>>>

If your condition is more complicated than just one value, you could do something like this:

>>> a = (i for i in a if not i in list_of_excluded_values)

Finally, as sweeneyrod points out in the comments, you can take a copy of a before you remove garbage with a_trimmed = a[:]

like image 40
wnnmaw Avatar answered Apr 08 '23 16:04

wnnmaw