1

I have these 3 arrays:

$a1 = array( 'a' => 1, 'b' => 2, 'c' => 3 );
$a2 = array( 'a' => 4, 'b' => 5, 'd' => 6 );
$a3 = array( 'a' => 7, 'c' => 8, 'd' => 9, 'x' => 10 );

I want to merge them so the result looks like this:

Array(
[a] => Array(
        [0] => 1
        [1] => 4
        [2] => 7
    )
[b] => Array(
        [0] => 2
        [1] => 5
        [2] => 
    )
[c] => Array(
        [0] => 3
        [1] => 
        [2] => 8
    )
[d] => Array(
        [0] => 
        [1] => 6
        [2] => 9
    )
[x] => Array(
        [0] => 
        [1] => 
        [2] => 10
    )

... and I will be using the data in a simple table like this:

  col-1 col-2  col-3
a   1     4      7
b   2     5      -
c   3     -      8
d   -     6      9
x   -     -     10

array_merge_recursive is close, but doesn't give me the empty elements, so I believe I need a loop to get the job done. My problem is figuring out which function I need to use in that loop.

I'd be happy just to merge 2 arrays at a time with a custom user function.

Jeff
  • 5,962
  • 16
  • 49
  • 81
  • Do you have only 3 arrays or N arrays ? – HamZa Mar 25 '13 at 09:35
  • I have more than 3 arrays and I need to keep track of which arrays have the "empty" element. – Jeff Mar 25 '13 at 09:43
  • Related, but does not tranpose the data structure: [Merge multiple associative arrays and add missing columns with a default value](https://stackoverflow.com/q/25972771/2943403) – mickmackusa Sep 16 '22 at 08:22

6 Answers6

5

I think the simplest approach to this would be obtain a list of all keys from all input arrays, then iterate the list of keys to construct the result array:

$keys = array_unique(
    array_merge(
        array_keys($a1),
        array_keys($a2),
        array_keys($a3)
    )
);

$result = array();
foreach ($keys as $key) {
    $result[$key] = array(
        isset($a1[$key]) ? $a1[$key] : null,
        isset($a2[$key]) ? $a2[$key] : null,
        isset($a3[$key]) ? $a3[$key] : null
    );
}

print_r($result);

See it working

...or if you want to supply an array of arrays with an arbitrary number of input arrays:

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

$result = array();
foreach ($keys as $key) {
    $result[$key] = array();
    foreach ($arrs as $arr) {
        $result[$key][] = isset($arr[$key]) ? $arr[$key] : null;
    }
}

print_r($result);

See it working

DaveRandom
  • 87,921
  • 11
  • 154
  • 174
4

Try this :

<?php
$a1    = array( 'a' => 1, 'b' => 2, 'c' => 3 );
$a2    = array( 'a' => 4, 'b' => 5, 'd' => 6 );
$a3    = array( 'a' => 7, 'c' => 8, 'd' => 9, 'x' => 10 );

$arr   = array($a1,$a2,$a3);
$cnt   = count($arr);

$res   = array();
foreach($arr as $key=>$val){
   foreach($val as $k=>$v){
     $res[$k][$key]  = $v;
   }
}
echo "<table>";
echo "<tr><td>&nbsp;</td><td>col-1</td><td>col-2</td><td>col-3</td></tr>";
foreach($res as $ky=>$vl){
   echo "<tr>";
   echo "<td>".$ky."</td>";
   for($i=0;$i<$cnt;$i++){
      if(array_key_exists($i,$vl)){
         echo "<td>".$vl[$i]."</td>";
      }
      else{
         echo "<td> - </td>";
      }
   }
   echo "</tr>";
}
echo "</table>";
?>

output :

    col-1   col-2   col-3
a   1       4       7
b   2       5       -
c   3       -       8
d   -       6       9
x   -       -       10
Prasanth Bendra
  • 31,145
  • 9
  • 53
  • 73
3

try this

<?php
 $a1 = array( 'a' => 1, 'b' => 2, 'c' => 3 );
 $a2 = array( 'a' => 4, 'b' => 5, 'd' => 6 );
$a3 = array( 'a' => 7, 'c' => 8, 'd' => 9, 'x' => 10 );
  function merge_common_keys(){
$arr = func_get_args();
$num = func_num_args();

$keys = array();
$i = 0;
for($i=0;$i<$num;++$i){
    $keys = array_merge($keys, array_keys($arr[$i]));
}
$keys = array_unique($keys);

$merged = array();

foreach($keys as $key){
    $merged[$key] = array();
    for($i=0;$i<$num;++$i){
        $merged[$key][] = isset($arr[$i][$key])?$arr[$i][$key]:null;
    }
}
  return $merged;
  }

$merged = merge_common_keys($a1,$a2,$a3);

print_r($merged);



$table = "<table>";




$table .= "<tr><td></td><td>col1</td><td>col2</td><td>col3</td></tr>";

foreach($merged as  $key=>$value)
  {
    $row = "<tr><td>$key</td>";
     foreach($value as $subvalue)
 {
   $row .= "<td>$subvalue</td>"; 
 }
 $table .= $row;
}
$table .= "</table>";
echo $table;
?>

ref : PHP, Merging arrays with common keys

see live demo http://codepad.viper-7.com/v8Ol5H

Community
  • 1
  • 1
alwaysLearn
  • 6,882
  • 7
  • 39
  • 67
1

You need to create something similar like array_merge_recursive().

But there might be a simpler solution, you say:

but doesn't give me the empty elements,

But you do know they don't exist!

So if you know the maximum amount of columns (amount of arrays) you need and you loop then you can always do:

if(isset($row[$column])) {
   echo $row[$column];//your column
} else {
   echo 0;
}
Timmetje
  • 7,641
  • 18
  • 36
1
function myMergeFunction() {

  $my_new_array = array();

  $arg_list = func_get_args();
  for ($i = 0; $i < count($arg_list); $i++) {

    foreach($arg_list[$i] as $key => $value) {
      if(!is_array($my_new_array[$key]))
        $my_new_array[$key] = array();

      $my_new_array[$key][] = $value

    }

  }

  return $my_new_array;

}

you can call it like:

myMergeFunction($a, $b, $c, $d, [...]);
Mihai Matei
  • 24,166
  • 5
  • 32
  • 50
1

→ Had already started on this before there where any answers, decided to finish it even though there are already acceptable answers. This version is more dynamic though and has some customization for the table's styling:

CODE:

/* Arrays from Question */  $a1 = array( 'a' => 1, 'b' => 2, 'c' => 3 ); $a2 = array( 'a' => 4, 'b' => 5, 'd' => 6 ); $a3 = array( 'a' => 7, 'c' => 8, 'd' => 9, 'x' => 10 );
/* Process Arrays       */  $result = handle_arrays( $a1, $a2, $a3 );
/* Create & Echo Table  */  echo ( array_table( $result ) );

function handle_arrays() {
    /* Get Arrays    */  $params = func_get_args(); $result = array();
    /* Merge Arrays  */  foreach( $params as $k=>$v ) { foreach( $v as $key=>$val ) { if( !array_key_exists( $key, $result ) ) $result[ $key ] = array(); $result[ $key ][ $k ] = $val; } }
    /* Handle Blanks */  for( $x = 0; $x < func_num_args(); $x++ ) { foreach( $result as $key=>$val ) { if( !array_key_exists( $x, $val ) ) { $result[ $key ][ $x ] = '-'; } ksort( $result[ $key ] ); } }
    /* Return Array  */  $return = array( func_num_args(), $result );
    return( $return );
}
function array_table( $array ) {
    /* Array # & Result Array */  $n = $array[ 0 ]; $a = $array[ 1 ];
    /* Style & Class Control  */  $padding_left = 10; $padding_right = 10; $col_align = "center"; $key_align = "left"; $table_class = ""; $col_class = ""; $row_class = ""; $field_class = "";
    /* Table & Column Headers */  $html = "<table class='{$table_class}'><tr><td style='padding-right:{$padding_right}px'></td>"; for( $x=0; $x<$n; $x++ ) { $html .= "<td style='padding-left:{$padding_left}px;padding-right:{$padding_right}px' class='{$col_class}'>col-$x</td>"; } $html .= "</tr>";
    /* Row and Fields Values  */  foreach( $a as $key=>$val ) { $html .= "<tr><td align='{$key_align}' class='{$row_class}'>$key</td>"; foreach( $val as $k=>$v ) { $html .= "<td align='{$col_align}' class='{$field_class}'>$v</td>"; } $html .= "</tr>"; } $html .= "</table>";
    return( $html );
}

OUTPUT:

    col-0   col-1   col-2
a     1       4       7
b     2       5       -
c     3       -       8
d     -       6       9
x     -       -       10
BIT CHEETAH
  • 1,200
  • 1
  • 7
  • 10