3

I'm trying to merge two arrays that have some overlapping results and some that are different, like this:

array(
 [0] => array('name' => 'John', 'score' => '9');
 [1] => array('name' => 'Pete', 'score' => '2');
 [2] => array('name' => 'Eric', 'score' => '7');
)

and

array(
 [0] => array('name' => 'Lisa', 'score' => '1');
 [1] => array('name' => 'Pete', 'score' => '5');
 [2] => array('name' => 'Mary', 'score' => '4');
)

This should result in one array of five (not six) results. The score for Pete should be the sum of his two scores, i.e. '7'.

Is there an easy function for this, or do I have to foreach one (or both?) lists and check them against eachother? I'm not sure how to get started on this, a pointer in the right direction would be appreciated!

edit:

So.. actually both arrays are populated with objects.. Any new ideas?

1
  • 1
    use mergesort and check for equality with previous elements during the merge part Commented Feb 28, 2011 at 12:42

5 Answers 5

2

Create a temporary lookup array and recreate your final array from it. This is a O(n) algorithm using extra space.See it here : http://codepad.org/4aL5KMR4

<?php

$arr1 =
array(
      array('name' => 'John', 'score' => '9'),
      array('name' => 'Pete', 'score' => '2'),
      array('name' => 'Eric', 'score' => '7'),
      );

$arr2=

array(
      array('name' => 'Lisa', 'score' => '1'),
      array('name' => 'Pete', 'score' => '5'),
      array('name' => 'Mary', 'score' => '4'),
      );

$res = array();
$revLookUp = array();
foreach($arr2 as $row)
{
  if(isset($revLookUp[$row['name']]) == true)
    $revLookUp[$row['name']] += $row['score'];
  else
    $revLookUp[$row['name']] = $row['score'];
}

foreach($arr1 as $row)
{
  if(isset($revLookUp[$row['name']]) == true)
    $revLookUp[$row['name']] += $row['score'];
  else
    $revLookUp[$row['name']] = $row['score'];
}


foreach($revLookUp as $key => $value){
  $res[] = array('name' => $key, 'score' => $value);
}

print_r($res);

?>
Sign up to request clarification or add additional context in comments.

2 Comments

This one has the same problem as Thariama's answer.. it turns the arrays into objects at the foreach
@stephan Thanks for pointing that out.We could alternatively traverse it with a for loop
1

There are no function for this task due to differents. Use this algorithm:

function merge($array1, $array2)
{
  $result = array();
  $count = (count($array1) > count($array2)) ? count($array1) : count($array2);
  for($i=0; $i<$count; $i++)
  {
    if($array1[$i]['name'] != $array2[$i]['name'])
    {
       $result[] = $array1[$i];
       $result[] = $array2[$i];
    }
    else
    {
       $array1['score'] += $array2['score'];
       $result[] = $array1[$i];
    }
  }
  return $result;
}

Sorry for my bad english. Good luck!

1 Comment

Thanks for the answer! I don't think it exactly does what I'm looking for though, for one it doesn't seem to add the scores? Anyway, I got an idea how to do this, that's all I needed.
1
function vector_sum($a, $b) {
  $arrays=func_get_args();
  $res=array(); $result=array();
  foreach($arrays as $current) {
    $res=array_reduce($current, function($res, cur){
      @$res[$cur['name']]+=$cur['score'];
      return $res;
    }, $res);
  }

  // sums done. put the result array in shape
  foreach ($res ad $name=>$score) 
    array_push($result, array('name'=>$name, 'score'=>$score));
  }
  return $result;
}

Not tested, it should works with an arbitrary arrays number

Comments

1

This will do the job

$array1 = array(
      array('name' => 'John', 'score' => 9),
      array('name' => 'Pete', 'score' => 2),
      array('name' => 'Eric', 'score' => 7),
      );

$array2 = array(
      array('name' => 'Lisa', 'score' => 1),
      array('name' => 'Pete', 'score' => 5),
      array('name' => 'Mary', 'score' => 4),
      );

$result = array();
$names = array();

foreach ($array2 as $elem2){
    $cc = 0;
    foreach ($array1 as $key => $elem1){
        $cc++;
        if ($elem1['name'] == $elem2['name']) {
            $names[$elem1['name']] = $elem1['score'] + $elem2['score'];
            break;
        }
        else if ($cc == count($array1)) {
            array_push ($result, $elem2);
        }
    }
}

foreach ($array1 as $elem1){
    if ($names[$elem1['name']]){
        $elem1['score'] = $names[$elem1['name']];
    }
    array_push ($result, $elem1);
}
print_r($result);

4 Comments

downvoted for reasons: badly formatted, incomplete answer (he asked for merging) and performance is not optimal
@Chimoo: my pc hanged and my edited (but not finished) post was submitted, please wait one more minute and my post will be ready
For some reason at the foreach the $array1 and $array2 actually turn into object..?
had to rework the whole thing a bit - this will work now for all cases
0

if you slightly re design you array as follows:

hope it helps

<?php

$a = array(
 'John' => '9',
 'Pete' => '2',
 'Eric' => '7',
);

$b = array(
 'Lisa' => '1',
 'Pete' => '5',
 'Mary' => '4',
);


$newArray = $a;
foreach($b as $key => $value) {
    if(array_key_exists($key, $newArray)){
     $newArray[$key] += $value;
    }else{
     $newArray[$key] = $value;
    }
}


print_r($newArray);


?>

also you can view the result here: http://codepad.org/9hKF8oVC

2 Comments

redesign makes it trival.perhaps it is not what he desired
yes you r right i agree, but it will only makes things easy for him, no need to go foreach twice.....

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.