0

I have multiple associative arrays, similar to the following:

$arr1 = array(0 => 12, 5 => 10, 19 => 48);
$arr2 = array(0 => 14, 7 => 9, 12 => 11, 19 => 30);

I would like to merge these arrays so that I have a single set of keys (0, 5, 7, 12, 19) and each points to an array with the values from the original arrays, and null if the value doesn't exist in the original array:

$merge = array(
    0 => array(12, 14),
    5 => array(10, null),
    7 => array(null, 9),
    12 => array(null, 11),
    19 => array(48, 30)
);

I need to be able to do this for an arbitrary number of arrays. I'm not sure where to start with this.

I could, I suppose, iterate through each array, append it's value to the result - but I'd have to check to see if I have the requisite number of elements in each resulting array before appending the current value to that index - which isn't terribly efficient.

Ideas or pointers?

Elie
  • 13,693
  • 23
  • 74
  • 128
  • I'd start with array_merge and then array_keys. – Nick Pickering Feb 20 '13 at 18:25
  • http://stackoverflow.com/questions/2165406/php-merge-duplicate-array-keys-in-a-multidimensional-array and a number of other dupes I think. – ficuscr Feb 20 '13 at 18:37
  • Not a dupe of that question - order here matters a great deal, which the other questions I've seen so far have not addressed – Elie Feb 20 '13 at 18:39

4 Answers4

1

EDIT

<?php
$arr1 = array(0 => 12, 5 => 10, 19 => 48);
$arr2 = array(0 => 14, 7 => 9, 12 => 11, 19 => 30);

foreach($arr1 as $k => $v){
 if(array_key_exists($k, $arr2)){
   $newarr[$k][] = $v;
   $newarr[$k][] = $arr2[$k];
 }else{
   $newarr[$k][] = $v;
   $newarr[$k][] = 'NULL';
 }
}

foreach($arr2 as $k => $v){
 if(!array_key_exists($k, $arr1)){
   $newarr[$k][] = 'NULL';
   $newarr[$k][] = $v;
 }
}

ksort($newarr);

echo '<pre>';
print_r($newarr);
?>

Output:

   Array
(
    [0] => Array
        (
            [0] => 12
            [1] => 14
        )

    [5] => Array
        (
            [0] => 10
            [1] => NULL
        )

    [7] => Array
        (
            [0] => NULL
            [1] => 9
        )

    [12] => Array
        (
            [0] => NULL
            [1] => 11
        )

    [19] => Array
        (
            [0] => 48
            [1] => 30
        )

)
  • how do you deal with the elements which exist in $secondloop which do not exist in $firstloop? – Elie Feb 20 '13 at 18:40
1

I think this is what you're looking for.

/*Merge function*/
function merge($a1, $a2)
{
    foreach($a1 as $key => $val)
        $a1[$key] = Array($a1[$key], null);
    foreach($a2 as $key => $val)
        $a1[$key] = Array((isset($a1[$key]))? $a1[$key][0]: null, $val);
    return ksort($a1);
}

/*Test*/
$arr1 = array(0 => 12, 5 => 10, 19 => 48);
$arr2 = array(0 => 14, 7 => 9, 12 => 11, 19 => 30);

foreach(merge($arr1, $arr2) as $key => $val){
    echo "<br />$key --";
    print_r($val);
}
/*output*/
0 --Array ( [0] => 12 [1] => 14 )
5 --Array ( [0] => 10 [1] => )
7 --Array ( [0] => [1] => 9 )
12 --Array ( [0] => [1] => 11 ) 
19 --Array ( [0] => 48 [1] => 30 )
CBusBus
  • 2,321
  • 1
  • 18
  • 26
1
    $arr1 = array(0 => 12, 5 => 10, 19 => 48);
    $arr2 = array(0 => 14, 7 => 9, 12 => 11, 19 => 30);

    $keys = array_merge(array_keys($arr1), array_keys($arr2));
    $merged = array();
    foreach ($keys as $key) {
        $merged[$key] = array(); 
        $merged[$key][] = isset($arr1[$key]) ? $arr1[$key] : null;
        $merged[$key][] = isset($arr2[$key]) ? $arr2[$key] : null;            
    }
    ksort($merged);
    echo '<pre>', var_dump($merged), '</pre>';

modified for an arbitrary number of arrays

    $arrays = array(
        array(0 => 12, 5 => 10, 19 => 48),
        array(0 => 14, 7 => 9, 12 => 11, 19 => 30),
        // ... more arrays
    );

    $keys = array();
    foreach ($arrays as $arr) {
        $keys = array_merge($keys, array_keys($arr));
    }

    $merged = array();
    foreach ($keys as $key) {
        $merged[$key] = array();
        foreach ($arrays as $arr) {
            $merged[$key][] = isset($arr[$key]) ? $arr[$key] : null;
        }         
    }
    ksort($merged);
    echo '<pre>', var_dump($merged), '</pre>';
Crisp
  • 11,417
  • 3
  • 38
  • 41
  • Thanks! This will cleanly work for an arbitrary number of arrays as well, with minor modifications - nice! – Elie Feb 20 '13 at 19:20
  • @Elie only spotted the comment that you figured out the arbitrary part from my original code after posting my edit (missed that condition initially, then got sidetracked with the phone, long story...) anyway, glad it helped :) – Crisp Feb 20 '13 at 19:38
0

Try this function:

   function multimerge ($array1, $array2) {
      if (is_array($array2) && count($array2)) {
         foreach ($array2 as $k => $v) {
            if (is_array($v) && count($v)) {
                $array1[$k] = multimerge($array1[$k], $v);
            } else {
                $array1[$k] = $v;
            }
         }
       } else {
          $array1 = $array2;
       }

       return $array1;
   }

http://php.net/manual/en/function.array-merge.php

mmcachran
  • 474
  • 2
  • 8