Say I have an iterator that returns 100 values. At some unpredictable point, the values switch from one category to another (in this case, ints to strs), and the action performed needs to change too (updating a variable to printing the number of characters).
The most basic example code I guess would be this:
def perform_operations(iterable):
most_recent_int = None
for item in iterable:
if type(item) is int:
most_recent_int = item
else:
print(f"int of {len(item)} characters")
return most_recent_int
iterable = list(range(100, 140)) + [str(i) for i in range(60)]
print(f"most recent int: {perform_operations(iterable)}")
This seems efficient, but that if statement also seems wasted on the last 59 or 60 entries as we can be sure the type of the items will not revert to int.
Here's a variant where two different suites are used, so that the last entries won't need an if statement:
def perform_operations(iterable):
most_recent_int = None
for item in (iterator := iter(iterable)):
if type(item) is int:
most_recent_int = item
else:
print(f"int of {len(item)} characters")
break
for remaining_str_item in iterator:
print(f"int of {len(remaining_str_item)} characters")
return most_recent_int
iterable = list(range(100, 140)) + [str(i) for i in range(60)]
print(f"most recent int: {perform_operations(iterable)}")
This looks like it should be more efficient.
The only thing I can think of that might perform fewer operations and possibly be interpreted quicker is:
def perform_operations(iterable):
most_recent_int = None
for item in (iterator := iter(iterable)):
if type(item) is int:
most_recent_int = item
else:
break
while True:
print(f"int of {len(item)} characters")
try:
item = next(iterator)
except StopIteration:
break
return most_recent_int
iterable = list(range(100, 140)) + [str(i) for i in range(60)]
print(f"most recent int: {perform_operations(iterable)}")
Or maybe:
from itertools import islice
def perform_operations(iterable):
most_recent_int = None
for i, item in enumerate(iterable):
if type(item) is int:
most_recent_int = item
else:
break
for remaining_str_item in islice(iterable, i, None):
print(f"int of {len(remaining_str_item)} characters")
return most_recent_int
iterable = list(range(100, 140)) + [str(i) for i in range(60)]
print(f"most recent int: {perform_operations(iterable)}")
Interested in the most efficient solutions, but also idiomatic and precedented solutions.