Weave 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.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log