Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transpose 2d array with inconsistent column structure [duplicate]

Array
(
    [0] => Array
        (
            [color] => Brown
        )

    [1] => Array
        (
            [color] => Green
        )

    [2] => Array
        (
            [width] => 34
        )

)

i need to make it like this

[color] => Array
    (
        [0] => green
        [1] => brown
    )

[width] => Array
    (
        [0] => 34
    )

)

i am trying with all the array tools. But i cant make it like i want it.

like image 475
Anthony De Meulemeester Avatar asked Apr 24 '26 21:04

Anthony De Meulemeester


2 Answers

This is fairly simple with array_column() (requires PHP >= 5.5.0):

$result = array[
  'color' => array_column($arr, 'color'),
  'width' => array_column($arr, 'width')
];

Live fiddle: https://eval.in/81746


If you do not know the keys beforehand, here is another solution using array_walk_recursive():
$result = [];
array_walk_recursive($arr, function($value, $key) use (&$result) {
  if (!isset($result[$key])) {
    $result[$key] = [];
  }
  $result[$key][] = $value;
});

Live fiddle: https://eval.in/81745

like image 114
ComFreek Avatar answered Apr 27 '26 11:04

ComFreek


So you want to merge the arrays recursively... if only such an array_merge_recursive function existed... Why don't you try this:

$a = array(
    array('colour' => 'green'),
    array('colour' => 'blue'),
    array('width' => 123)
);
$result = array();
foreach($a as $arr)
{
    $result = array_merge_recursive($result, $arr);
}
var_dump($result);

That worked pretty darn well for me, as you can see for yourself here, too

True, in the given example width won't be an array, so you get:

array('colour' => array('green','blue'),'width' => 123);

If you need everything to be an array, then a dirty fix would be to use a cast:

foreach($result as $k => $v) $result[$k] = (array) $v;

Reassigning the $result values a second time, only casting them as an array ensures that all values will, evidently, be arrays. An array that is cast to an array will remain unchanged, just like (int) 1 still evaluates to 1. A primitive value (strings, integers, doubles,...) will be wrapped int an array, but an object will be transformed into an array, so be careful. If objects are likely to occur in this array:

foreach($result as $k => $v) $result[$k] = is_array($v) ? $v : array($v);

is probably the safer bet. However, I chose not to go for this approach as I still find it pretty tedious and silly to wrap everything up into an array, containing only 1 value...

For those of you with a strange preference for unmaintainable code, the following one-liner is a condensed, but notice free & working example of the same code:

foreach($a as $arr) $result = array_merge_recursive(isset($result) ? $result : array(), $arr);

This is as a response to Stuart Wakefield who suggested a one-liner using call_user_func_array, which is something I'll always oppose, for as long as I live and breathe, BTW...

like image 21
Elias Van Ootegem Avatar answered Apr 27 '26 11:04

Elias Van Ootegem