views:

67

answers:

4

Hello,

I actually am quite embarrassed to ask such a question but it is one of those days that you spend 10 thousand hours on the simplest of functions and the more you try to solve them the more complicated a solution you get.... I don't want to waste more time so here is the problem.

I have one array:

  $items=array(
    0=> array('name'=>'red','value'=>2),
    1=> array('name'=>'black','value'=>1),
    2=> array('name'=>'red','value'=>3)
  );

And I need a function that detects the identical names and merges them adding up their values. This means after the function finishes the array should look like this:

  $items=array(
    0=>array('name'=>'red','value'=>5),
    1=>array('name'=>'black','value'=>1)
  );

('red' has two entries that have values 2 and 3, after the operation, red should have 1 entry with the value 5)

Thanks.

+1  A: 

First off, can you simply make it an associative array so that it handles itself for you?

$items = array(
    'red' => 5,
    'black' => 1,
);

If not, you could always do it by copying the array in a loop (not the best, but it works every time):

$newItems = array();
foreach ($items as $item) {
    if (!isset($newItems[$item['name']])) {
        $newItems[$item['name']] = $item;
    } else {
        $newItems[$item['name']]['value'] += $item['value'];
    }
}
$items = array_values($newItems);
ircmaxell
well, this was the first solution that came in mind, but instead of using "!isset" as anyone more clever than a stone would do, I decided to find if "count($newItems)>0" , which of course is not the right approach but the continuation is almost similar to this. Thanks anyway...it works...
chosta
Well, one point on `clever`. [Debugging is twice as hard as writing the code in the first place. Therefore if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.](http://stackoverflow.com/questions/1103299/help-me-understand-this-brian-kernighan-quote). So don't get too caught up in the "cleverness" or "beauty" of code... Pick something that works, and is maintainable first...
ircmaxell
You are right, I usually try to make things work, then I try to make them work faster (clever). In this case I just got stuck in my own mind, forgetting that I can actually convert the array back using array_values(). It is just one of those days that nothing works as you need it to...thanks anyway..have a nice day yourself.
chosta
+1  A: 

That should do the job:

// create a asssociative array with the name as the key and adding the values
$newitems = array():
foreach($items as $item){
  $newitems[$item["name"]] += $item["value"]:
}
// unset the original array by reinitializing it as an empty array
$items = array():
// convert the newitems array the the old structure
foreach($newitems as $key => $item){
  $items[] = arraz("name" => $key, "value" => $item):
}
Kau-Boy
One minor point. Please always initialize your variables. So you `unset($items)`. Then you'll need an `$items = array();` (which would have sufficed by itself in this case)...
ircmaxell
Sorry usually do. I have forgotten it on this one. Will edit my answer.
Kau-Boy
+1  A: 

Something like this should be about as good as it gets:

$map = array();
foreach ($items as $i => $item)
{
  if (!array_key_exists($item['name'], $map))
    $map[$item['name']] = $i;
  else
  {
    $items[$map[$item['name']]]['value'] += $item['value'];
    unset($items[$i]);
  }
}

Note that this modifies the original $items array.

konforce
+1  A: 

take a look of these codes

moustafa