Question

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.

Was it helpful?

Solution 2

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...

OTHER TIPS

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

I guess this should do it, especially if you don't know what keys you will have:

foreach ($original_array as $val1)
    foreach ($val1 as $key2=>$val2)
        $merged_array[$key2][] = $val2;

just use foreach like below -- arrayName = your original array --

foreach($arrayName as $newArr){
 if($newArr['color']){
   $tempArr['color'][] = $newArr['color'];
  }
 if($newArr['width']){
  $tempArr['width'][] = $newArr['width'];
 }
}

Building upon Elias's array_merge_recursive answer, the following introduces a small fix to turn single item merge into an array:

/* This version uses the function array_merge_recursive to collect
 * all of the values for the nested arrays by key
 *
 * @see http://willem.stuursma.name/2011/09/08/parallel-array_map-with-hiphop/
 * @see http://willem.stuursma.name/2010/11/22/a-detailed-look-into-array_map-and-foreach/ 
 * for why for loops are better than array_map in general
 */
$result = array_map(function($item) {

    /* The array_merge_recursive function doesn't add
     * values to an array if there was only one found
     * if the item isn't an array, make it an array
     */
    return is_array($item) ? $item : array($item);

/* Calls the array_merge_recursive function applying all of
 * the nested arrays as parameters.
 *
 * @see http://php.net/array_merge_recursive
 * @see http://www.php.net/call_user_func_array
 */
}, call_user_func_array('array_merge_recursive', $arr));

Produces:

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

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

Instead of:

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

        [width] => 34
    )

Alternatively, a dynamic approach to ComFreek's array_column solution.

This gives you the array of the keys:

/* Gets the keys of the nested arrays as a single array of keys by first
 * mapping the nested arrays to an array of keys they contain and then
 * by merging these arrays and killing duplicates
 *
 * @see http://php.net/function.array-unique
 * @see http://www.php.net/call_user_func_array
 * @see http://www.php.net/array_merge
 * @see http://www.php.net/array_map
 */
$keys = array_unique(call_user_func_array('array_merge', array_map(function($item) {

    /* Replaces the nested array of keys and values with an array
     * of keys only in the mapped array
     *
     * @see http://www.php.net/array_keys
     */
    return array_keys($item);
}, $arr)));

As:

Array
    (
        [0] => color
        [1] => width
    )

Which can be used with this snippet:

/* Combines the array of keys with the values from the nested
 * arrays.
 *
 * @see http://php.net/array_combine
 * @see http://www.php.net/manual/en/function.array-map.php
 */
$result = array_combine($keys, array_map(function($key) use($arr) {

    /* Collects the values from the nested arrays
     *
     * @see http://php.net/array_column
     */
    return array_column($arr, $key);
}, $keys));

To create the desired output:

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

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

Note: functional calls can be beneficial in most languages over an imperative style although it does require a shift mentally. Functional patterns open up the possibilities of low level optimizations that otherwise wouldn't be possible. Array map, for example, could be executed in parallel, whereas a for loop cannot, the for loop will always have a restriction that it must execute sequentially.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top