As you expect several results per call, it is the best to use a generator function:
def get_bad_results(person_results):
for i in person_results:
if i[1]>i[3] or i[1]<i[2]:
yield i[0]
or a generator expression:
def get_bad_results(person_results):
return (i[0] for i in person_results if i[1]>i[3] or i[1]<i[2])
so that
test_results = [["White blood cells",8.5,2,7],
["Neutrophils",5.3,2.5,5],
["Red blood cells", 12.4, 9,15]]
for i in get_bad_results(test_results):
print i
print list(get_bad_results(test_results))
print ", ".join(get_bad_results(test_results))
gives the output
White blood cells
Neutrophils
['White blood cells', 'Neutrophils']
White blood cells, Neutrophils
For the other function, do
def count_healthy(all_results):
counter = 0
for i in all_results:
if len(list(get_bad_results(i))) == 0:
counter += 1
return counter
or just
def count_healthy(all_results):
return sum(1 for i in all_results if len(list(get_bad_results(i))) == 0)
Edit:
For many get_bad_results()
, turning it into a list could be memory-intensive.
So instead of len(list(get_bad_results(i))) == 0
you could use
def has_results(it):
"""Returns True if the iterator it yields any items."""
return next((True for _ in it), False)
and then
def count_healthy(all_results):
return sum(1 for i in all_results if not has_results(get_bad_results(i)))