PHP - 将单个数组转换为多维数组[关闭]

I'm newbie in PHP.

I need send data for API purpose.

I have array print_r($detail) like this

Array
(
    [0] => Array
        (
            [id] => item1
        )
    [1] => Array
        (
            [price] => 300
        )
    [2] => Array
        (
            [quantity] => 1
        )
    [3] => Array
        (
            [id] => item2
        )
    [4] => Array
        (
            [price] => 400
        )
    [5] => Array
        (
            [quantity] => 2
        )
)

And I want convert it to multidimensional before sending to another process, like

Array
(
    [0] => Array
        (
            [id] => item1
            [price] => 300
            [quantity] => 1
        )
    [1] => Array
        (
            [id] => item2
            [price] => 400
            [quantity] => 2
        )
)

How it is possible?

Something like this should do it

$newArray = array();
$newRow = array();
foreach ($array as $row) {
    $key = array_keys($row)[0];
    $value = array_values($row)[0];
    if ($key == 'id') {
        $newArray[] = $newRow;
    }
    $newRow[$key] = $value;
}
$newArray[] = $newRow;

You can split your $details array into multiple chunks. I've written the following function which accepts a custom chunk size (note count($initialArray) % $chunkSize === 0 must be true):

function transformArray(array $initialArray, $chunkSize = 3) {
    if (count($initialArray) % $chunkSize != 0) {
        throw new \Exception('The length of $initialArray must be divisible by ' . $chunkSize);
    }

    $chunks = array_chunk($initialArray, 3);
    $result = [];

    foreach ($chunks as $chunk) {
        $newItem = [];

        foreach ($chunk as $item) {
            $newItem[array_keys($item)[0]] = reset($item);
        }

        $result[] = $newItem;
    }

    return $result;
}

Given your details array, calling transformArray($details) will result in:

enter image description here

The customizable chunk size allows you to add more data to your source array:

$details = [
    ['id' => 'item1'],
    ['price' => 300],
    ['quantity' => 1],
    ['anotherProp' => 'some value'],
    ['id' => 'item2'],
    ['price' => 400],
    ['quantity' => 2],
    ['anotherProp' => 'another value'],
];

The function call is now transformArray($details, 4);:

enter image description here

This version looks for repeat keys then creates a new Array whenever they are the same so you could have some different data. Hope it helps.

function customMulti($customArray){
  $a = array(); $n = -1; $d;
  foreach($customArray as $i => $c){
    foreach($c as $k => $v){
      if(!isset($d)){
        $d = $k;
      }
      if($k === $d){
        $a[++$n] = array();
      }
      $a[$n][$k] = $v;
    }
  }
  return $a;
}
$wow = customMulti(array(array('id'=>'item1'),array('price'=>300),array('quantity'=>1),array('id'=>'item2'),array('price'=>400),array('quantity'=>2)));
print_r($wow);

This version may be with the same result of @PHPglue answer. But this takes only one foreach. I think this is faster, more efficient way as stated here by one of the Top SO Users.

enter image description here

Try to look if you want it.

Live Demo

<?php

function explodeArray($arr)
{
    $newArr = array();
    foreach($arr as $row)
    {
        $key = array_keys($row)[0];
        $curArr = count($newArr) > 0 ? $newArr[count($newArr)-1] : array();
        if( array_key_exists($key, $curArr) )
        {
            array_push($newArr, array($key=>$row[$key]) );
        }
        else
        {
            $index = count($newArr) > 0 ? count($newArr) - 1 : 0 ;
            $newArr[$index][$key] = $row[$key];
        }
    }
    return $newArr;
}

Different Arrays for testing.

$detail = array(
        array('id'=>'item1'),
        array('price'=>300),
        array('quantity'=>1),
        array('id'=>'item2'),
        array('price'=>400),
        array('quantity'=>2)
    );

var_dump( explodeArray($detail) );

$detail_match = array(
        array('id'=>'item1'),
        array('price'=>300),
        array('quantity'=>1),
        array('newkey'=>'sample'),
        array('id'=>'item2'),
        array('price'=>400),
        array('quantity'=>2),
        array('newkey'=>'sample')
    );

var_dump( explodeArray($detail_match) ); // Works with any size of keys.

$detail_diff_key = array(
        array('id'=>'item1'),
        array('price'=>300),
        array('quantity'=>1),
        array('diff1'=>'sample1'),
        array('id'=>'item2'),
        array('price'=>400),
        array('quantity'=>2),
        array('diff2'=>'sample2')
    );

var_dump( explodeArray($detail_diff_key) ); // Works with any size of keys and different keys.

$detail_unmatch = array(
        array('id'=>'item1'),
        array('price'=>300),
        array('quantity'=>1),
        array('unmatchnum'=>'sample1'),
        array('id'=>'item2'),
        array('price'=>400),
        array('quantity'=>2)
    );

var_dump( explodeArray($detail_unmatch) );

I think this little block of code work for you.

Use:

$detail = array(
    "0" => array("id" => "item1"),
    "1" => array("price" => "300"),
    "2" => array("quantity" => "1"),
    "3" => array("id" => "item2"),
    "4" => array("price" => "400"),
    "5" => array("quantity" => "2"),
    "6" => array("id" => "item3"),
    "7" => array("price" => "500"),
    "8" => array("quantity" => "3")
);

$i = 0;
$j = 0;
$multi_details = array();
while($j < count($detail)){
    $multi_details[$i][id] = $detail[$j++][id];
    $multi_details[$i][price] = $detail[$j++][price];
    $multi_details[$i][quantity] =  $detail[$j++][quantity];
    $i++;
}
echo '<pre>';
print_r($multi_details);
echo '</pre>';

Output:

Array
(
    [0] => Array
        (
            [id] => item1
            [price] => 300
            [quantity] => 1
        )

    [1] => Array
        (
            [id] => item2
            [price] => 400
            [quantity] => 2
        )

    [2] => Array
        (
            [id] => item3
            [price] => 500
            [quantity] => 3
        )

)