| name | iterate-with-itertools |
| description | For combinatorial iteration: permutations, combinations, cartesian products, without storing all results in memory. |
iterate-with-itertools
When to Use
- Need all permutations of a sequence
- Need all combinations of k items
- Need cartesian product of multiple sequences
- Chaining multiple iterables
- Grouping consecutive elements
When NOT to Use
- Simple loop is clearer
- Only need a few specific elements
- Need random access to results
The Pattern
Use itertools for memory-efficient iteration over combinatorial structures.
from itertools import permutations, combinations, product, chain
list(permutations('ABC'))
list(combinations('ABCD', 2))
list(product('AB', '12'))
list(chain([1,2], [3,4], [5]))
for perm in permutations(range(10)):
if is_valid(perm):
break
Example (from pytudes)
from itertools import permutations, combinations, product
def brute_force_tsp(cities):
start, *rest = cities
return min(
([start] + list(perm) for perm in permutations(rest)),
key=tour_length
)
deck = [r + s for r in 'A23456789TJQK' for s in 'SHDC']
hands = combinations(deck, 5)
def roll(n, sides=6):
"""Distribution of sums from rolling n dice."""
from collections import Counter
die = range(1, sides + 1)
return Counter(sum(roll) for roll in product(die, repeat=n))
for L, R in product(left_expressions, right_expressions):
for op in ['+', '-', '*', '/']:
combine(L, op, R)
def splits(sequence):
"""All ways to split sequence into two non-empty parts."""
return ((sequence[:i], sequence[i:])
for i in range(1, len(sequence)))
Key Principles
- Lazy by default: itertools returns iterators, not lists
- product with repeat:
product(range(6), repeat=3) for 3 dice
- combinations_with_replacement: Allow same item multiple times
- chain.from_iterable: Flatten nested iterables
- islice for limits:
islice(permutations(...), 100) for first 100