Join arrays by equal keys, but separating values

4

Scenario (example):

I have 2 Arrays , X and Y (dynamically created, individual ):

$arX = Array('AAA' => 173.696, 'BBB' => 72.436, 'CCC' => 142.692);
$arY = Array('AAA' => 127, 'DDD' => 72.333);


Objective:

What you would like is to join them by key, but separate values .

Example of the expected result:

Array
    (
        [AAA] => Array
        (
            [X] => 173.696,
            [Y] => 127
        )
        [BBB] => Array
        (
            [X] => 72.436
        )
        [CCC] => Array
        (
            [X] => 142.692
        )
        [DDD] => Array
        (
            [Y] => 72.333
        )
    )


Questions:

  • Is there a native function for this?
  • How could I get the result?
asked by anonymous 13.08.2018 / 15:23

3 answers

1

<?php

function mesclar(array $arrX, array $arrY)
{
    //Cria uma nova array
    $z = array();

    //Pega as chaves de ambas arrays
    $chaves = array_merge( array_keys($arrX), array_keys($arrY) );

    foreach ($chaves as $chave)
    {
        // A performance do '=== false' é minima ou nenhuma na maioria dos casos, mas se o array for gigante mesmo talvez isto torne o script razoavelmente mais performatico
        if (isset($z[$chave]) === false) {
            $z[$chave] = array();
        }

        //Copia o valor do primeiro array para X
        if (array_key_exists($chave, $arrX))
        {
            $z[$chave]['X'] = $arrX[ $chave ];
        }

        //Copia o valor do primeiro array para Y
        if (array_key_exists($chave, $arrY))
        {
            $z[$chave]['Y'] = $arrY[ $chave ];
        }
    }

    return $z;
}

$arX = array('AAA' => 173.696, 'BBB' => 72.436, 'CCC' => 142.692);
$arY = array('AAA' => 127, 'DDD' => 72.333);

$novaArray = mesclar($arX, $arY);

print_r( $novaArray );

Example in IDEONE: link

    
13.08.2018 / 16:14
2

You can use the array_walk function to accomplish what you need.

The central point is to refer to callback which is the new array you will create ( $newArray ) and, as third parameter of array_walk , the key prefix (which can be X , Y or any other key you want, if there are more arrays).

$arX = Array('AAA' => 173.696, 'BBB' => 72.436, 'CCC' => 142.692);
$arY = Array('AAA' => 127, 'DDD' => 72.333);
$newArray = [];

$callback = function($value, $key , $prefix) use (&$newArray)
{
    //valida se a chave já existe no array
    if (!array_key_exists($key , $newArray))
    {
        $newArray[$key] = [];
    }

    // Adiciona o novo array ao já existente, utilizando o prefixo enviado via parâmetro.
    $newArray[$key] += [$prefix => $value];
};

//Cada array será processado individualmente e adicionado em $newArray
//que é referenciado no callback.
array_walk($arX , $callback , "X");
array_walk($arY , $callback , "Y");

Result:

array(4) {
  ["AAA"]=>
  array(2) {
    ["X"]=>
    float(173.696)
    ["Y"]=>
    int(127)
  }
  ["BBB"]=>
  array(1) {
    ["X"]=>
    float(72.436)
  }
  ["CCC"]=>
  array(1) {
    ["X"]=>
    float(142.692)
  }
  ["DDD"]=>
  array(1) {
    ["Y"]=>
    float(72.333)
  }
}

Working Code: link

    
13.08.2018 / 16:16
1

I had tried to give a more elaborate answer using sophisticated array functions, but nothing was easier than using foreach itself.

See:

$result = [];

foreach ($arX as $key => $value)
{
    $result[$key]['X'] = $value;
}

foreach ($arY as $key => $value)
{
    $result[$key]['Y'] = $value;
}


var_dump($result);

Result:

[
 "AAA" => [
   "X" => 173.696,
   "Y" => 127,
 ],
 "BBB" => [
   "X" => 72.436,
 ],
 "CCC" => [
   "X" => 142.692,
 ],
 "DDD" => [
   "Y" => 72.333,
 ],
]

If you still want to insist on using functions to do this, you can combine the power of array_merge_recursive with array_map .

view:

$result = array_merge_recursive(
    array_map(function ($x) { return ['X' => $x]; }, $arX),
    array_map(function ($y) { return ['Y' => $y]; }, $arY)
);

In a third option, you could use the + operator along with array_keys to iterate with all keys of your array.

See:

$result = [];

foreach (array_keys($arX + $arY) as $key) {

    if (isset($arX[$key]))
        $result[$key]['X'] = $arX[$key];

    if (isset($arY[$key]))
        $result[$key]['Y'] = $arY[$key];
}
    
13.08.2018 / 16:12