Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cartesian Product Laravel Package

bentools/cartesian-product

Generate the cartesian product (all combinations) from a multidimensional array with a low-memory iterator. Supports dynamic values via closures that can inspect the partial combination. Iterate results or dump them to an array when needed.

View on GitHub
Deep Wiki
Context7

Latest Stable Version License CI Workflow Coverage Total Downloads

Cartesian Product

A simple, low-memory footprint function to generate all combinations from a multi-dimensionnal array.

Usage

use function BenTools\CartesianProduct\combinations;

$data = [
    'hair' => [
        'blond',
        'black'
    ],
    'eyes' => [
        'blue',
        'green',
        function (array $combination) { // You can use closures to dynamically generate possibilities
            if ('black' === $combination['hair']) { // Then you have access to the current combination being built
                return 'brown';
            }
            return 'grey';
        }
    ]
];

foreach (combinations($data) as $combination) {
    printf('Hair: %s - Eyes: %s' . PHP_EOL, $combination['hair'], $combination['eyes']);
}

Output:

Hair: blond - Eyes: blue
Hair: blond - Eyes: green
Hair: blond - Eyes: grey
Hair: black - Eyes: blue
Hair: black - Eyes: green
Hair: black - Eyes: brown

Array output

Instead of using foreach you can dump all possibilities into an array.

[!WARNING] This will dump all combinations in memory, so be careful with large datasets.

print_r(combinations($data)->asArray());

Output:

Array
(
    [0] => Array
        (
            [hair] => blond
            [eyes] => blue
        )

    [1] => Array
        (
            [hair] => blond
            [eyes] => green
        )

    [2] => Array
        (
            [hair] => blond
            [eyes] => grey
        )

    [3] => Array
        (
            [hair] => black
            [eyes] => blue
        )

    [4] => Array
        (
            [hair] => black
            [eyes] => green
        )

    [5] => Array
        (
            [hair] => black
            [eyes] => brown
        )

)

Combinations count

You can simply count how many combinations your data produce (this will not generate any combination):

use function BenTools\CartesianProduct\combinations;

$data = [
    'hair' => [
        'blond',
        'red',
    ],
    'eyes' => [
        'blue',
        'green',
        'brown',
    ],
    'gender' => [
        'male',
        'female',
    ]
];
var_dump(count(combinations($data))); // 2 * 3 * 2 = 12

Filtering combinations

You can filter combinations using the filter method. This is useful if you want to skip some combinations based on certain criteria:

use function BenTools\CartesianProduct\combinations;

$data = [
    'hair' => [
        'blond',
        'black'
    ],
    'eyes' => [
        'blue',
        'green',
    ]
];

foreach (combinations($data)->filter(fn (array $combination) => 'green' !== $combination['eyes']) as $combination) {
    printf('Hair: %s - Eyes: %s' . PHP_EOL, $combination['hair'], $combination['eyes']);
}

Map output

You can use the each method to transform each combination into a different format:

use App\Entity\Book;

use function BenTools\CartesianProduct\combinations;

$books = [
    'author' => ['Isaac Asimov', 'Arthur C. Clarke'],
    'genre' => ['Science Fiction', 'Fantasy'],
]

foreach (combinations($books)->each(fn (array $combination) => Book::fromArray($combination)) as $book) {
    assert($book instanceof Book);
}

Installation

PHP 8.2+ is required.

composer require bentools/cartesian-product

Performance test

The following example was executed on my Core i7 personnal computer with 8GB RAM.

use function BenTools\CartesianProduct\combinations;

$data = array_fill(0, 10, array_fill(0, 5, 'foo'));

$start = microtime(true);
foreach (combinations($data) as $c => $combination) {
    continue;
}
$end = microtime(true);

printf(
    'Generated %d combinations in %ss - Memory usage: %sMB / Peak usage: %sMB',
    ++$c,
    round($end - $start, 3),
    round(memory_get_usage() / 1024 / 1024),
    round(memory_get_peak_usage() / 1024 / 1024)
);

Output:

Generated 9765625 combinations in 1.61s - Memory usage: 0MB / Peak usage: 1MB

Unit tests

./vendor/bin/pest

Other implementations

th3n3rd/cartesian-product

patchranger/cartesian-iterator

Benchmark

See also

bentools/string-combinations

bentools/iterable-functions

Credits

Titus on StackOverflow - you really rock.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor