Asher
Asher

Reputation: 80

How to generate multiple combinations from a multidimensional array

I am importing products from one platform to another using CSV. I have successfully created arrays of products from the CSV file but have difficulty creating variations from these product arrays.

A product array looks like this

Array
(
    [Name] => Test Product
    [Price] => 50
    [Options] => Array
        (
            ['Color'] => Array
                (
                    ['Red'] => 10
                    ['Green'] => 20
                )

            ['Size'] => Array
                (
                    ['Small'] => 30
                    ['Medium'] => 40
                )

        )

)

The desired output for the variations array is

Array
(
    [0] => Array
        (
            [Name] => Test Product - Red, Small
            [Regular price] => 80
        )

    [1] => Array
        (
            [Name] => Test Product - Red, Medium
            [Regular price] => 100
        )

    [2] => Array
        (
            [Name] => Test Product - Green, Small
            [Regular price] => 100
        )

    [3] => Array
        (
            [Name] => Test Product - Green, Medium
            [Regular price] => 110
        )

)

My PHP code is as follows

<?php
    echo "<pre>";
    $product = array(
        "Name" => "Test Product",
        "Price" => 50,
        "Options" => array(
            "'Color'" => array(
                "'Red'" => 10,
                "'Green'" => 20,
            ),
            "'Size'" => array(
                "'Small'" => 30,
                "'Medium'" => 40,
            )
        ),
    );
    print_r($product);
    
    $variations = array();
    foreach ($product["Options"] as $option) {
        foreach ($option as $name => $price) {
            $name = str_replace("'", "", $name);
            array_push($variations, array(
                "Name" => "Test Product - ${name}",
                "Price" => (int)$product["Regular price"] + $price,
            ));
        }
    }
    print_r($variations);

I am stuck on combining the Options. The goal is to merge the options. I tried various possibilities using the for loop and the nested for loop but had no luck. Can someone please guide me in the right direction? Thank you

Upvotes: 0

Views: 393

Answers (1)

IT goldman
IT goldman

Reputation: 19485

This is somewhat of a cartesian product of N arrays. See comments for references.

Explanation: The real trick here is to create the arrays multiplication. For that I've used this answer. Please print_r the resulting array after cartesian and you'll see how it multiplied the arrays.

Next step is just printing them nicely. Another hurdle is to get the values of the price back for each item ("red", "green" etc) and for that I just use the original array looking for the correct prices.

I admit, there are a lot of array_keys, array_values and array_map there. Maybe could have made this entire solution inside one function. But I went with reusing the cartesian without changing it.


function cartesian($input)
{
    $result = array(array());
    foreach ($input as $key => $values) {
        $append = array();
        foreach ($result as $product) {
            foreach ($values as $item) {
                $product[$key] = $item;
                $append[] = $product;
            }
        }
        $result = $append;
    }
    return $result;
}

$arr = array(
    "Name" => "Test Product",
    "Price" => 50,
    "Options" => array(
        'Color' => array(
            'Red' => 10,
            'Green' => 20,
        ),
        'Size' => array(
            'Small' => 30,
            'Medium' => 40,
        ),
    ),
);

$options = array_map('array_keys', $arr["Options"]);

$combinations = cartesian($options);

$result = array_map(function ($combo) use ($arr) {
    // get prices
    $total = 0;
    foreach ($combo as $key => $value) {
        $total += $arr['Options'][$key][$value];
    }
    return [
        'name' => $arr['Name'] . " - " . implode(", ", array_values($combo)),
        'Regular price' => $arr['Price'] + $total,
    ];

}, $combinations);

print_r($result);

Output:

Array
(
    [0] => Array
        (
            [name] => Test Product - Red, Small
            [Regular price] => 90
        )

    [1] => Array
        (
            [name] => Test Product - Red, Medium
            [Regular price] => 100
        )

    [2] => Array
        (
            [name] => Test Product - Green, Small
            [Regular price] => 100
        )

    [3] => Array
        (
            [name] => Test Product - Green, Medium
            [Regular price] => 110
        )

)

Upvotes: 1

Related Questions