I'd just use a simple loop without the generator expression.
total = count = 0
for e, s in zip(education, salary):
if e == '0' and s > 0:
total += s
count += 1
mean = total / count
Though if you already only have the iterator of preprocessed values, then tzaman's would be my choice. Then again, you're considering to "count again my stream", so apparently you are in control of the code so could do it without the generator.
Measuring memory usage and runtime of the various working solutions for larger input (100,000 elements):
original 406.72 KB 7.0 ms result = 24.990380884305115
Kelly_Bundy 0.24 KB 10.1 ms result = 24.990380884305115
tzaman 0.40 KB 11.6 ms result = 24.990380884305115
user2390182 6155.90 KB 16.0 ms result = 24.990380884305115
alparslan_mimaroğlu 441.23 KB 21.4 ms result = 24.990380884305115
user1740577 406.86 KB 7.2 ms result = 24.990380884305115
Code (Try it online!):
from random import choices
from itertools import tee
import tracemalloc
import functools
from timeit import repeat
def original(education, salary):
list_of_les = [s for e, s in zip(education, salary) if e=='0' and s>0]
return sum(list_of_les)/len(list_of_les)
def Kelly_Bundy(education, salary):
total = count = 0
for e, s in zip(education, salary):
if e == '0' and s > 0:
total += s
count += 1
return total / count
def tzaman(education, salary):
low_edu = (s for e, s in zip(education, salary) if e=='0' and s>0)
total, count = 0, 0
for salary in low_edu:
total += salary
count += 1
return total / count
def user2390182(education, salary):
s, c = map(sum, zip(*((s, 1) for e, s in zip(education, salary) if e=='0' and s>0)))
return s / c
def alparslan_mimaroğlu(education, salary):
knowns = map(lambda x: x[1] , filter(lambda x: x[0] == '0' and x[1] != 0, zip(education, salary)))
(knowns1, knowns2) =tee(knowns, 2)
return sum(knowns1) / sum(1 for _ in knowns2)
def user1740577(education, salary):
sum_len = lambda t : (sum(t), len(t))
s,c = sum_len([s for e, s in zip(education, salary) if e=='0' and s>0])
return s / c
def main():
n = 10 ** 5
education = choices(['0', '1'], k=n)
salary = choices(range(50), k=n)
def test(function):
tracemalloc.start()
result = function(iter(education), iter(salary))
memory = tracemalloc.get_traced_memory()[1]
tracemalloc.stop()
time = min(repeat(lambda: function(iter(education), iter(salary)), number=1))
print('%20s' % function.__name__,
'%7.2f KB ' % (memory / 1e3),
'%4.1f ms ' % (time * 1e3),
'result =', result)
for _ in range(3):
for function in original, Kelly_Bundy, tzaman, user2390182, alparslan_mimaroğlu, user1740577:
test(function)
print()
main()