Viacheslav Nefedov
Viacheslav Nefedov

Reputation: 2399

Python 3: perform additional calculation inside a generator

The question is about sport programming. I'm getting a huge string from stdin and I have to create a byte array with one byte for each char with True value if the char equals to '.' and with False value otherwise. At the same time I should calculate amount of cases when we have two '.' symbols near each other.

Question 1: can be some additional calculation performed inside a generator expression to be accessible after the generator was used - sum, count, more complex calculation to avoid additional looping over the created list?

Question 2: can I access the previous loop result inside a generator expression? I try to perform the second solution below in one generator expression.

Because of this is for competition no external libraries can be used.

1st solution

res = 0: prev = False
s = bytearray()
for c in (c == '.' for c in 'a' + input() + 'a'):
    res += c and prev
    prev = c
    s.append(c)

2nd solution

s = bytearray(c == '.' for c in 'a' + input() + 'a')
res = sum(map(all,zip(s[1:],s[:-1])))

UPD: 3rd solution with itertools.tee() - unfortunately this solution faster than 1st but slower than 2nd

i1,i2,i3 = tee((c == '.' for c in 'a' + input() + 'a'),3)
next(i1)
res = sum(a and b for a,b in zip(i1,i2))
s = bytearray(i3)

Upvotes: 2

Views: 102

Answers (1)

Kasravnd
Kasravnd

Reputation: 107337

Question 1: can be some additional calculation performed inside a generator expression to be accessible after the generator was used - sum, count, more complex calculation to avoid additional looping over the created list?

No generators are one shut iterables and you can not use them after one iteration.

Question 2: can I access the previous loop result inside a generator expression? I try to perform the second solution below in one generator expression.

So if you want to access the previous item in a generator expression you can simply use zip on your iterable :

inp='a' + input() + 'a'
(next=='.' and pre== '.' for pre,next in zip(inp,inp[1:]))  

But if you want to access to previous item of a generator you can use itertools.tee to create 2 independent iterators from your generator and use zip function to create a new generator (in python 2 use itertools.izip)contain pairs with prev and next items.

from itertools import tee
new_generator,MY_generator=tee(MY_generator)
next(new_generator)

zipped_generator = zip(new_generator,My_generator)

And in iteration do :

[for pre,next in zipped_generator]

Upvotes: 2

Related Questions