Home > Back-end >  Transpose a multidimensional array with variable depth (2 levels and 3 levels)
Transpose a multidimensional array with variable depth (2 levels and 3 levels)

Time:02-06

I need to restructure an array containing data in 2 levels and 3 levels. All of the values should be grouped by their indexes, but I need to maintain associative relationships.

Sample input:

$variation = [
    "sku" =>  [
        0 => "dSADad",
        1 => "ASDAF",
        2 => "ASFAS",
    ],
    "Price" => [
        0 => "1",
        1 => "1",
        2 => "1",
    ],
    "Quantity" =>  [
        0 => "123",
        1 => "123",
        2 => "123434",
    ],
    "attributes" => [
        "Color" => [
            0 => "5",
            1 => "4",
            2 => "4",
        ],
        "Size" =>  [
            0 => "3",
            1 => "3",
            2 => "2",
        ],
        "Material" =>  [
            0 => "7",
            1 => "7",
            2 => "8",
        ],
    ],
];

I want to transform it to be grouped by separate variants. I tried several options but without a successful result. I also tried with JS to add an index to the input before submitting, but it still doesn't work. The only option left is to transform it into PHP.

Desired result:

$variations = [
    [
        "sku" => "dSADad",
        "Price" => "1",
        "Quantity" => "123",
        "attributes" => [
            "Color" => "5",
            "Size" => "3",
            "Material" => "7",
        ],
    ],
    [
        "sku" => "ASDAF",
        "Price" => "1",
        "Quantity" => "123",
        "attributes" => [
            "Color" => "4",
            "Size" => "3",
            "Material" => "7",
        ],
    ],
    [
        "sku" => "ASFAS",
        "Price" => "1",
        "Quantity" => "123434",
        "attributes" => [
            "Color" => "4",
            "Size" => "2",
            "Material" => "8",
        ],
    ],
];

CodePudding user response:

I managed to make this piece of code:

function extractVariation($variations, $key)
{
    $variation = [];
    foreach ($variations as $property => $values) {
        if (isset($values[$key])) {
            $variation[$property] = $values[$key];
        } else {
            $variation[$property] = extractVariation($values, $key);
        }
    }
    return $variation;
}

$newVariations = [];

foreach ($variations['sku'] as $key => $sku) {
    $newVariations[] = extractVariation($variations, $key);
}

var_export($newVariations);

See a working example here: https://3v4l.org/l4gJQ

Note that I renamed your $variation array into $variations.

The function is recursive, which allows it to go into the attributes array.

The output is:

array (
  0 => 
  array (
    'sku' => 'dSADad',
    'Price' => '1',
    'Quantity' => '123',
    'attributes' => 
    array (
      'Color' => '5',
      'Size' => '3',
      'Material' => '7',
    ),
  ),
  1 => 
  array (
    'sku' => 'ASDAF',
    'Price' => '1',
    'Quantity' => '123',
    'attributes' => 
    array (
      'Color' => '4',
      'Size' => '3',
      'Material' => '7',
    ),
  ),
  2 => 
  array (
    'sku' => 'ASFAS',
    'Price' => '1',
    'Quantity' => '123434',
    'attributes' => 
    array (
      'Color' => '4',
      'Size' => '2',
      'Material' => '8',
    ),
  ),
)

It is always better to show what you've tried, even if it doesn't work completely. That way people here can see that you're not simply asking them to write code for you, but that you really have a problem.

CodePudding user response:

For your sample data, it is not necessary to use recursion because the input array's depth is known/static.

Traditional array transposition (with a 2d array) is the nesting of two foreach loops and switching the keys between the two levels. With your data, you must conditionally handle the data sets that have 3 levels of depth. Notice the how inside of the is_array() condition, another loop is used to iterate the subarray and push that data into the new appropriate position in the result array.

In all cases, the level containing indexed keys is used as the new first level key and the original first level keys are always used as new second level keys.

Code: (Demo)

$result = [];
foreach ($array as $k1 => $v1) {
    foreach ($v1 as $k2 => $v2) {
        if (is_array($v2)) {
            foreach ($v2 as $k3 => $v3) {
                $result[$k3][$k1][$k2] = $v3;
            }
        } else {
            $result[$k2][$k1] = $v2;
        }
    }
}
var_export($result);
  • Related