Комбинаторное итерирование
April 26, 2026 · View on GitHub
Инструменты для комбинаторного итерирования: декартово произведение, перестановки, сочетания, сочетания с повторениями, булеан (множество всех подмножеств).
Product
Декартово произведение коллекций.
Выходные кортежи — массивы-списки (индексы с нуля, в порядке входных коллекций); исходные ключи отбрасываются. Порядок соответствует itertools.product из Python (лексикографический, с сохранением порядка входов): самая правая коллекция «пробегает» быстрее всех.
Входные коллекции должны быть конечными. Они потребляются один раз (материализуются внутри), поэтому генераторы поддерживаются, но повторно итерироваться не могут.
Особые случаи:
product()без аргументов возвращает один пустой кортеж:[[]]- если любая входная коллекция пуста, результат пуст
Combinatorics::product(iterable ...$iterables): \Generator
use IterTools\Combinatorics;
$numbers = [1, 2];
$letters = ['a', 'b'];
foreach (Combinatorics::product($numbers, $letters) as $tuple) {
print_r($tuple);
}
// [1, 'a']
// [1, 'b']
// [2, 'a']
// [2, 'b']
Permutations
Перестановки элементов коллекции.
Выходные кортежи — массивы-списки (индексы с нуля, в порядке входной коллекции); исходные ключи отбрасываются. Порядок соответствует itertools.permutations из Python (лексикографический по позиции во входе, а не по значению): одинаковые значения различаются по позиции, поэтому permutations([1, 1]) даёт [[1, 1], [1, 1]].
Входная коллекция должна быть конечной. Она потребляется один раз (материализуется внутри), поэтому генераторы поддерживаются, но повторно итерироваться не могут.
Особые случаи:
$r = 0даёт один пустой кортеж:[[]]- если
$rбольшеcount($data), результат пуст $r = nullозначает перестановки полной длины (эквивалентно$r = count($data))- пустой вход с
$r = null(или$r = 0) даёт один пустой кортеж:[[]]
Выбрасывает \InvalidArgumentException, если $r отрицательное.
Combinatorics::permutations(iterable $data, ?int $r = null): \Generator
use IterTools\Combinatorics;
$data = [1, 2, 3];
foreach (Combinatorics::permutations($data) as $tuple) {
print_r($tuple);
}
// [1, 2, 3]
// [1, 3, 2]
// [2, 1, 3]
// [2, 3, 1]
// [3, 1, 2]
// [3, 2, 1]
Combinations
Сочетания (без повторений) элементов коллекции.
Выходные кортежи — это list-массивы (с 0-индексацией, в порядке входа); ключи исходной коллекции игнорируются. Порядок выхода соответствует Python's itertools.combinations (лексикографический по позиции во входе, не по значению): дублирующиеся значения считаются уникальными по позиции: combinations([1, 1], 2) даёт [[1, 1]].
Входная коллекция должна быть конечной. Она потребляется один раз (материализуется внутри), поэтому генераторы поддерживаются, но их нельзя перебирать повторно.
Особые случаи:
$r = 0даёт один пустой кортеж:[[]]- если
$rбольшеcount($data), результат пуст $r = count($data)даёт ровно один кортеж, содержащий все элементы входа
Выбрасывает \InvalidArgumentException, если $r отрицательное.
Combinatorics::combinations(iterable $data, int $r): \Generator
use IterTools\Combinatorics;
$data = [1, 2, 3, 4];
foreach (Combinatorics::combinations($data, 2) as $tuple) {
print_r($tuple);
}
// [1, 2]
// [1, 3]
// [1, 4]
// [2, 3]
// [2, 4]
// [3, 4]
Combinations With Replacement
Сочетания с повторениями элементов коллекции.
Выходные кортежи — это list-массивы (с 0-индексацией, в порядке входа); ключи исходной коллекции игнорируются. Порядок выхода соответствует Python's itertools.combinations_with_replacement (лексикографический по позиции во входе, не по значению): дублирующиеся значения считаются уникальными по позиции и могут давать дублирующиеся выходные кортежи: combinationsWithReplacement([1, 1], 2) даёт [[1, 1], [1, 1], [1, 1]].
Входная коллекция должна быть конечной. Она потребляется один раз (материализуется внутри), поэтому генераторы поддерживаются, но их нельзя перебирать повторно.
В отличие от combinations(), $r может превышать count($data) — элементы повторяются.
Особые случаи:
$r = 0даёт один пустой кортеж:[[]]- пустой вход с
$r > 0даёт пустой результат - пустой вход с
$r = 0даёт один пустой кортеж:[[]]
Выбрасывает \InvalidArgumentException, если $r отрицательное.
Combinatorics::combinationsWithReplacement(iterable $data, int $r): \Generator
use IterTools\Combinatorics;
$data = [1, 2, 3];
foreach (Combinatorics::combinationsWithReplacement($data, 2) as $tuple) {
print_r($tuple);
}
// [1, 1]
// [1, 2]
// [1, 3]
// [2, 2]
// [2, 3]
// [3, 3]
Powerset
Все подмножества коллекции, упорядоченные по длине, а внутри каждой длины — по позиции во входе.
Выходные подмножества — это list-массивы (с 0-индексацией, в порядке входа); ключи исходной коллекции игнорируются. Подмножества отдаются в порядке возрастания длины; внутри каждой длины порядок совпадает с Combinatorics::combinations (лексикографический по позиции во входе, не по значению), поэтому дублирующиеся значения считаются уникальными по позиции: powerset([1, 1]) даёт [[], [1], [1], [1, 1]].
Входная коллекция должна быть конечной. Она потребляется один раз (материализуется внутри), поэтому генераторы поддерживаются, но их нельзя перебирать повторно.
Внимание: булеан из
nэлементов содержит2**nподмножеств — расход растёт экспоненциально. Вход из 20 элементов даёт более миллиона подмножеств; вход из 30 элементов — более миллиарда.
Особые случаи:
- пустой вход даёт одно пустое подмножество:
[[]]
Combinatorics::powerset(iterable $data): \Generator
use IterTools\Combinatorics;
$data = [1, 2, 3];
foreach (Combinatorics::powerset($data) as $subset) {
print_r($subset);
}
// []
// [1]
// [2]
// [3]
// [1, 2]
// [1, 3]
// [2, 3]
// [1, 2, 3]
use IterTools\Combinatorics;
// Перебрать все комбинации фича-флагов для параметризованных тестов.
$flags = ['darkMode', 'beta', 'analytics'];
foreach (Combinatorics::powerset($flags) as $enabled) {
print_r($enabled);
}
// []
// ['darkMode']
// ['beta']
// ['analytics']
// ['darkMode', 'beta']
// ['darkMode', 'analytics']
// ['beta', 'analytics']
// ['darkMode', 'beta', 'analytics']
См. также Stream::powerset.