I'm trying to iterate a bunch of data ranges at once, to get the combinations of all their values.
The number of ranges can differ, but I have them collected in a list.
Is there a way to iterate them using list comprehension or a similar clean, pythonic way?
This is what I mean by iterating together:
[print(i, j) for i in r1 for j in r2]
So that's a simple example with two known ranges, but what I need is more like
[print(i, j, ...) for i in r1 for j in r2 for k in r3...]
Note: i don't just need a list of number combinations, the iterators are my own iterator class which works similarly to range()
but allows me to also get current state without calling next()
, which would alter the state.
My iterator class sets its value back to the start on StopIteration, so it can be looped through more than once.
Here you can see the class:
@dataclass
class Range:
start: float
end: float
step: float = field(default=1)
includeEnd: bool = field(default=True)
def __post_init__(self):
self.value = self.start
def __next__(self):
v = self.value
end = v > self.end if self.includeEnd else v >= self.end
if not end:
self.value += self.step
return v
else:
self.value = self.start
raise StopIteration
def __iter__(self):
return self
itertools.product()
.range
is not an iterator.itertools.product()
;-) It doesn't care whether your pass it iterators or iterables. It materializes each argument's sequence once at the start, into internal tuples, then iterates as many times as needed across those internal tuples.