Merge all values at the same array level, at the same level

Asked

Viewed 1,243 times

6

I got 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 a loop, I want all index values 0, be in the same set, that is to say, [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 any function native for that reason ?

If not, how would you ?

3 answers

4

I don’t know a way Native to do this, so I made an example that solves this question:

A very basic form 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

  • Very good ! I tried to do by foreach but did not know this function is_arrray, there was no way. Although it works perfectly, the form of Isac, in my view, is simpler, and uses native functions. Even so, thank you so much ! + 1

3


Short Version

There is yes:

$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 actually a native function that can do this and calls if array_map considering the particular case of passing null as first parameter, which corresponds to callback. One of the examples of documentation (Example #4) has an interesting note to it:

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

In this example the array_map is called with null and with the 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);

Where the result will construct an array of arrays with a value of each interspersed:

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 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 exit:

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
        )

)

See the result in Ideone

However it turns out to be rigid because it forces not only know the keys as the amount of elements it has. To get around this problem you can follow a solution a little further down in the documentation that puts null at the beginning of the array with array_unshift and then expand all parameters to 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 exit.

See this solution also in Ideone

Detailing array_unshift and call_user_func_array

The array_unshift is only used to add a value to the start. So imagine you have an array like this:

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

In doing array_unshift($arr, null); he’s gonna get null at first, as if it had been built like this:

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

The call_user_func_array will take the given function and call it passing as parameters all values of the given array. Imagine you have the array defined above:

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

In doing call_user_func_array("array_map", $arr); It’s like he called directly the array_map as follows:

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

This would not be possible to do manually as 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"]);.

  • The array_unshift serves to play all arrays for 1 level only !?

  • @RBZ array_unshift serves to add an element to the beginning of the "array". In this case it is intended to null at the beginning to be later as the 1st parameter of the array_map

  • array_unshift. The call_user_func_array I didn’t quite understand what he does. The array_map he needs a map, but the call_user_func_array calls the array_map and use some map ?

  • @RBZ I will already detail a little more in the answer. What the call_user_func_array makes is to call the array_map "expanding" each array value as parameter. That is, if $arr = [null, 1,2,3,4] in making call_user_func_array("array_map", $arr) would amount to having done array_map(null,1,2,3,4).

  • @RBZ I detailed a little the answer with explanations in the face of these two functions. If you are not very clear just say that I try to detail a little more.

  • No dude, it’s perfect. It met the need by using the native functions. Thank you so much !

  • There in the example of array_map, the line $b = array("um", "dois", "tres", "quatro", "cinco"); is wrong, should be in English, but I think the translation of the documentation translates unintentionally there. ;)

  • @RBZ haha, well done. I didn’t even notice! And now that you mention it, I had to look about 2 or 3 times to notice. It would be good to suggest this correction in the official documentation. Anyway I’ve already got the answer right.

Show 3 more comments

1

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

//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:

  • 1

    Not devaluing your attempt to help, the answer seems very fragile as it will fail in 3 cases: 1) unordered values 2) arrays of different sizes 3) other array quantity

  • Disordered arrays do not mean, the function array_multisort will sort. Regarding the amount of arrays can be made a array_merge dynamic. The only fault really is the division into multiple array with array_chunk

  • The ordination affects due to the sort. Try using as second array [25, 200, 300] and see the result it gives you.

  • I did the code following the example of the question, ie exact numbers, 10, 100, 1000, ... I know that it is not perfect, but I believe it will be difficult to find something native that does what the question wants perfectly, simply and easily. I showed only one option that exists for the shown case

  • @Guilhermecostamilam As Isac said, if the array is not "ordered", which may occur, the array_multisort with the array_merge will not work as it would mess up the data by ordering incorrectly. For example 'B' => array(300,200,100)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.