Merge all values on the same level of the array, on the same level

7

I have the following array :

Array
(
    [A] => Array
        (
            [0] => 10
            [1] => 20
            [2] => 30
        )

    [B] => Array
        (
            [0] => 100
            [1] => 200
            [2] => 300
        )

    [C] => Array
        (
            [0] => 1000
            [1] => 4000
            [2] => 9000
        )

)

In loop , I want all index values 0 , to be in the same set, that is, [0]([A][0] [B][0] [C][0]) .

Expected result:

Array
(
    [0] => Array
        (
            [0] => 10
            [1] => 100
            [2] => 1000
        )

    [1] => Array
        (
            [0] => 20
            [1] => 200
            [2] => 4000
        )

    [2] => Array
        (
            [0] => 30
            [1] => 300
            [2] => 9000
        )

)

Is there a native function to do this?

If not, how would you do it?

    
asked by anonymous 05.05.2018 / 17:54

3 answers

4

Short Version

There is:

$resultado = array_map(null, $arr["A"], $arr["B"], $arr["C"]);

or:

array_unshift($arr, null);
$resultado = call_user_func_array("array_map", $arr);

Long Version

There is indeed a native function that can do this and calls itself array_map considering the particular case of passing null as the first parameter, which corresponds to the callback. One of the examples of documentation (Example # 4) has an interesting note on this:

  

An interesting way to use this function is to construct an array of arrays, which can easily be done using NULL as the name of the callback function.

In this example, array_map is called with null and with 3 arrays relevant:

$a = array(1, 2, 3, 4, 5);
$b = array("um", "dois", "tres", "quatro", "cinco");
$c = array("uno", "dos", "tres", "cuatro", "cinco");

$d = array_map(null, $a, $b, $c);

In that the result will construct an array of arrays with a value of each one intercaladamente:

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => um
            [2] => uno
        )

    [1] => Array
        (
            [0] => 2
            [1] => dois
            [2] => dos
        )
    ...

Applying this idea to your code could start with something simple indicating each of the indices to interpret, which correspond to the sub-arrays:

$arr = array(
    'A' => array(10,20,30),
    'B' => array(100,200,300),
    'C' => array(1000,4000,9000)
);

$res = array_map(null, $arr["A"], $arr["B"], $arr["C"]);
print_r($res);

That gives you the following output:

Array
(
    [0] => Array
        (
            [0] => 10
            [1] => 100
            [2] => 1000
        )

    [1] => Array
        (
            [0] => 20
            [1] => 200
            [2] => 4000
        )

    [2] => Array
        (
            [0] => 30
            [1] => 300
            [2] => 9000
        )

)

View the result on Ideone

However it turns out to be rigid because strength does not only know the keys as the amount of elements it has. To work around this problem you can follow a slightly lower solution in the documentation that puts null at the beginning of the array with array_unshift "and then expand all parameters for the map function with call_user_func_array :

$arr = array(
    'A' => array(10,20,30),
    'B' => array(100,200,300),
    'C' => array(1000,4000,9000)
);

array_unshift($arr, null);
$res = call_user_func_array("array_map", $arr);
print_r($res);

That gives you exactly the same output.

See this solution also in Ideone

Detailing array_unshift and call_user_func_array

The array_unshift is only used to add a value at startup. So I figured I'd have an array like this:

$arr = Array(1, 2, 3, 4, 5);

When doing array_unshift($arr, null); it will get null at the beginning, as if it were built like this:

$arr = Array(null, 1, 2, 3, 4, 5);

The call_user_func_array will pick up the indicated function and call it by passing all the values of the indicated array as parameters. Imagine you have the array defined above:

$arr = Array(null, 1, 2, 3, 4, 5);

By doing call_user_func_array("array_map", $arr); it is as if you have directly called array_map as follows:

array_map(null, 1, 2 , 3, 4, 5);

This would not be possible to do manually since the amount of parameters would change depending on the amount of elements in the array, which is actually the first example I gave with array_map(null, $arr["A"], $arr["B"], $arr["C"]); .

    
06.05.2018 / 03:30
4

I do not know a Native way to do this, so I've done an example that solves this question:

A very basic way is:

<?php

$data = array(
    'A' => array(10,20,30),
    'B' => array(100,200,300),
    'C' => array(1000,2000,3000)
    );      

$data_new = array();
foreach($data as $key => $values)
{
    if (is_array($values))
    {
        for($i = 0; $i < count($values); $i++)
        {
            $data_new[$i][] = array_shift($data[$key]);         
        }   
    }

}

print_r($data_new);

OnLine Example

From this example you can make a function for this code:

<?php

$data = array(
    'A' => array(10,20,30),
    'B' => array(100,200,300),
    'C' => array(1000,2000,3000)
    );

function union($data)
{
    $data_old = $data;
    $data_new = array();
    foreach($data_old as $key => $values)
    {
        if (is_array($values))
        {
            for($i = 0; $i < count($values); $i++)
            {
                $data_new[$i][] = array_shift($data_old[$key]);         
            }   
        }
    }

    return ($data_new); 
}

print_r(union($data));

OnLine Example

    
05.05.2018 / 18:33
1

A single function I believe does not exist but you can use some joins:

//Uni os array
$array = array_merge($array[0], $array[1], $array[2]);

//Ordena os array como string, assim ficará [10, 100, 1000, 20, ...]
array_multisort($array, SORT_ASC, SORT_STRING);

//Divide novamente o array em partes
$array = array_chunk($array, 3);

//Resultado final
var_dump($array);

Documentation:

05.05.2018 / 18:57