0

I have 2 arrays. Something like this .

  $res1 = [
     ['ID' => 60,'TOTAL' => 500],
     ['ID' => 61,'TOTAL' => 600],
     ['ID' => 63,'TOTAL' => 500]
  ];
 $res2 = [
     ['ID' => 60,'TOTAL' => 600],
     ['ID' => 61,'TOTAL' => 700],
     ['ID' => 64,'TOTAL' => 800]
  ];

I want to merge $res1 and $res2 array with Ids and sum the totals if IDs are equal else if ids do not match, then I should keep that as well in array.

This is what I have tried and need help to improve it more in terms performance as well .

 foreach ($res1 as $id1 => $val1) {
        foreach ($res2 as $id2 => $val2) {
            $r =array();
            if ($val1['ID'] == $val2['ID']) {
                $r['ID'] = $val1['ID'];
                $r['TOTAL'] = $val1['TOTAL'] + $val2['TOTAL'];
            }else{
                // MISSING Something here 
            }
            $result[] = $r;
        }

    }

Expected result should be

$result = [
     ['ID' => 60,'TOTAL' => 1100],
     ['ID' => 61,'TOTAL' => 1300],
     ['ID' => 63,'TOTAL' => 500],
     ['ID' => 64,'TOTAL' => 800]
  ];
priyanka hj
  • 79
  • 1
  • 2
  • 11
  • Working with these arrays cannot be very efficient. How did you get them like this? A better arrays would be: `$totals1 = [60 => 500, 61 => 600, 63 => 500];` and `$totals2 = [60 => 600, 61 => 700, 64 => 800];`. – KIKO Software Jul 25 '19 at 09:22
  • Possibly duplication of https://stackoverflow.com/questions/5881443/merging-arrays-with-the-same-keys – Cafer Yükseloğlu Jul 25 '19 at 09:22
  • @KIKOSoftware I can't change the array representation. Possibly need solution with the existing one – priyanka hj Jul 25 '19 at 09:42

5 Answers5

1

Before I present this answer, if this came from a database table, it is much better to just do the sum in that layer. That said, when the array grows, it will be slower.

What I would do is get all the IDs first. Then loop based on all of the IDs and then search their respective totals and sum. Like so:

$result = [];
$ids = array_unique(array_merge(array_column($res1, 'ID'), array_column($res2, 'ID')));
foreach ($ids as $id) {
    if (empty($result[$id])) { // initialization
        $result[$id] = ['ID' => $id, 'TOTAL' => 0];
    }

    $res1_key = array_search($id, array_column($res1, 'ID'));
    $res2_key = array_search($id, array_column($res2, 'ID'));

    $sum = array_sum([
        $res1_key !== false ? $res1[$res1_key]['TOTAL'] : 0,
        $res2_key !== false ? $res2[$res2_key]['TOTAL'] : 0,
    ]);

    $result[$id]['TOTAL'] = $sum;
}

Basically get all the ids present on both first and second array. Loop it based on IDS, initialize the container, search the ID total on both, then sum, then assign it in the container that was initialized.

Sidenote: This only takes into account one unique ID per array set. If there are duplicates in both arrays like $res1 has two ID = 60, it can be retrofitted to use array_keys to get multiple search values instead of array_search.

Kevin
  • 41,694
  • 12
  • 53
  • 70
0
$res1 = [
    ['ID' => 60,'TOTAL' => 500],
    ['ID' => 61,'TOTAL' => 600],
    ['ID' => 63,'TOTAL' => 500]
 ];
$res2 = [
    ['ID' => 60,'TOTAL' => 600],
    ['ID' => 61,'TOTAL' => 700],
    ['ID' => 64,'TOTAL' => 800]
 ];

 //store result here
 $result = array();

 //check duplicates in res1
 foreach($res1 as $r1){
    $has_pair = false;
    foreach($res2 as $r2){
        if($r1['ID'] == $r2['ID']){
            //if res 1 has a duplicate, then add them both
            $has_pair = true;
            $arr = array(
                'ID' => $r1['ID'],
                'TOTAL' => ($r1['TOTAL'] + $r2['TOTAL']),
            );
           //add them to $result
            array_push($result,$arr);
        }
    }
    if(!$has_pair){
        //if pair in $res1 then add them here instead
        array_push($result,$r1);
    }
 }

 //check duplicates for res2
 foreach($res2 as $r1){
    $has_pair = false;
    foreach($result as $r2){
        if($r1['ID'] == $r2['ID']){
            $has_pair = true;
        }
    }
    if(!$has_pair){
        array_push($result,$r1);
    }
 }
 print_r($result);
NJY404
  • 349
  • 3
  • 14
0

You can use function array_walk. My solution more faster than using foreach in foreach or using array_search. Here link to solution https://3v4l.org/tC8Xu

<?php
$res1 = [
     ['ID' => 60,'TOTAL' => 500],
     ['ID' => 61,'TOTAL' => 600],
     ['ID' => 63,'TOTAL' => 500]
  ];
 $res2 = [
     ['ID' => 60,'TOTAL' => 600],
     ['ID' => 61,'TOTAL' => 700],
     ['ID' => 64,'TOTAL' => 800]
  ];

  function summTotal(&$result, $parts) {
    array_walk($parts, function($item) use (&$result){
      if (isset($result[$item['ID']])) {
          $result[$item['ID']]['TOTAL'] += $item['TOTAL']; 
      } else {
          $result[$item['ID']] = $item;
      }
    });
  }

  $result = [];

  summTotal($result, $res1);
  summTotal($result, $res2);

  print_r($result);
potiev
  • 546
  • 2
  • 11
0

You can use the below code


$res1 = [
   ['ID' => 60,'TOTAL' => 500],
   ['ID' => 61,'TOTAL' => 600],
   ['ID' => 63,'TOTAL' => 500]
];
$res2 = [
    ['ID' => 60,'TOTAL' => 600],
    ['ID' => 61,'TOTAL' => 700],
    ['ID' => 64,'TOTAL' => 800]
];

$results = array();

foreach( array_merge( $res1, $res2) as $r ) {
    if( !isset ( $results [ $r['ID'] ] ) ) {
        $results[ $r['ID'] ] = 0;
    }

    $results[ $r['ID'] ]  += $r['TOTAL'];
} 

$reformatResults = array();

foreach( $results as $key => $total ) {
    $reformatResults[$key] = $total;
}
echo '<pre>';
print_r($reformatResults);

Check the demo here. https://3v4l.org/Z6Bhv

ascsoftw
  • 3,466
  • 2
  • 15
  • 23
0

try this

$result = [];
$merge = array_merge($res1,$res2);
$resId = array_unique(array_column($merge,'ID'));
foreach ($resId as $vId) {
    $tempValue = [];
    foreach ($merge as $vm) {
        if (!array_key_exists($vId, $tempValue)) {
            $tempValue[$vId] = 0;
        }

        if ($vId == $vm['ID']) {
            $tempValue[$vId] += $vm['TOTAL']; 
        }
    }

    $result[] = ['ID' => $vId,'TOTAL' => $tempValue[$vId]];
}

return json_encode($result);