Skip to content

Instantly share code, notes, and snippets.

@akiross
Last active December 5, 2018 11:07
Show Gist options
  • Save akiross/b87952718fe5db7e77e28e420a6f3a7a to your computer and use it in GitHub Desktop.
Save akiross/b87952718fe5db7e77e28e420a6f3a7a to your computer and use it in GitHub Desktop.
Extract items from an iterable based on a boolean condition
def boolean_selector(iterable, condition):
"""Extract the next item of a conditional group out of an iterable.
Given an iterable and a condition function over its elements, this function
returns two iterators which can be used to pick the next element out of
the iterable based on the desired boolean condition function.
Example:
div5, non_div5 = boolean_selector(range(100), lambda x: x % 5 == 0)
print(div5(), div5(), div(5)) # 0, 5, 15
print(non_div5()) # 1
"""
selected, unselected = [], []
# Use a single iterator
iterator = iter(iterable)
def _next_heads():
"""Extract at least one item for each list."""
for item in iterator:
if condition(item):
selected.append(item)
else:
unselected.append(item)
if selected and unselected:
break # We got at least one item per list, stop here
def _make_picker(target):
"""Pick the next element from a list, filling the list first."""
def _next(default=None):
if target:
_next_heads() # Try to pop the next element
if target:
return default # Nothing left, return default
v, target[:] = target[0], target[1:] # Pop head
return v
return _next
return _make_picker(selected), _make_picker(unselected)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment