How to sum array value of duplicate data
Asked Answered
T

5

2

I have an array with some of same ID value as shown in below.

[
    {"ID":"126871","total":"200.00","currency":"USD","name":"John"},
    {"ID":"126872","total":"2000.00","currency":"Euro","name":"John"},
    {"ID":"126872","total":"1000.00","currency":"Euro","name":"John"},
    {"ID":"126872","total":"500.00","currency":"USD","name":"John"},
    {"ID":"126872","total":"1000.00","currency":"Euro","name":"John"},
]

If the ID value is duplicate, sum the total value of the same currency. For the different currency of same ID, no need to sum total.

Here is what I want.

[
    {"ID":"126871","total":"200.00","currency":"USD","name":"John"},
    {"ID":"126872","total":"4000.00","currency":"Euro","name":"John"},
    {"ID":"126872","total":"500.00","currency":"USD","name":"John"}
]

I am stuck with the above problem. I already tried as much as I can. But I got the wrong result. I'm very appreciative for any advice.

Tymothy answered 1/9, 2016 at 7:43 Comment(2)
It looks like JS array of objects.Baugh
" I already tried as much as I can" - Well, share what you tried with us and we might be able to help. We won't do all the work for you.Hersch
C
2

@Cloud I have made function for your requirement and Thanks @M. I. for look into this sum section.

$array = array(
    array("ID"  => "126871","total"=>"200.00","currency"=>"USD","name"=>"John"),
    array("ID"  => "126872","total"=>"2000.00","currency"=>"Euro","name"=>"John"),
    array("ID"  => "126872","total"=>"1000.00","currency"=>"Euro","name"=>"John"),
    array("ID"  => "126872","total"=>"500.00","currency"=>"USD","name"=>"John"),
    array("ID"  => "126872","total"=>"1000.00","currency"=>"Euro","name"=>"John"),
);
echo "<pre>";
print_r($array);

function unique_multidim_array($array, $key,$key1,$addedKey) { 
    $temp_array = array(); 
    $i = 0; 
    $key_array = array(); 
    $key1_array = array(); 

    foreach($array as $val) { 
        if (!in_array($val[$key], $key_array) && !in_array($val[$key1], $key1_array)) { 
            $key_array[$i] = $val[$key]; 
            $key1_array[$i] = $val[$key1]; 
            $temp_array[$i] = $val; 
        }else{
            $pkey = array_search($val[$key],$key_array);
            $pkey1 = array_search($val[$key1],$key1_array);
            if($pkey==$pkey1){
                $temp_array[$pkey][$addedKey] += $val[$addedKey];
            }else{
                $key_array[$i] = $val[$key]; 
                $key1_array[$i] = $val[$key1]; 
                $temp_array[$i] = $val; 
            }
            // die;
        }
        $i++; 
    } 
    return $temp_array; 
} 

$nArray = unique_multidim_array($array,"ID","currency","total");
// die;
print_r($nArray);
die;
Cynic answered 1/9, 2016 at 9:31 Comment(0)
L
1

You will need to:

  • Convert your json string to a php array with json_decode.
  • Loop through the rows and group them using compound temporary keys. In other words generate a single string from each row's ID & currency values and use that string as the temporary unique key.
  • Sum the grouped row's total values.
  • Then prepare the output array for its return to json by reindexing the rows and calling json_encode().

Code: (Demo)

$json='[
    {"ID":"126871","total":"200.00","currency":"USD","name":"John"},
    {"ID":"126872","total":"2000.00","currency":"Euro","name":"John"},
    {"ID":"126872","total":"1000.00","currency":"Euro","name":"John"},
    {"ID":"126872","total":"500.00","currency":"USD","name":"John"},
    {"ID":"126872","total":"1000.00","currency":"Euro","name":"John"}
]';

$array=json_decode($json,true);  // convert to array
foreach($array as $row){
    if(!isset($result[$row['ID'].$row['currency']])){
        $result[$row['ID'].$row['currency']]=$row;  // on first occurrence, store the full row
    }else{
        $result[$row['ID'].$row['currency']]['total']+=$row['total'];  // after first occurrence, add current total to stored total
    }
}
$result=json_encode(array_values($result));  // reindex the array and convert to json
echo $result;  // display

Output:

[
    {"ID":"126871","total":"200.00","currency":"USD","name":"John"},
    {"ID":"126872","total":4000,"currency":"Euro","name":"John"},
    {"ID":"126872","total":"500.00","currency":"USD","name":"John"}
]
Lavaliere answered 21/12, 2017 at 14:25 Comment(0)
E
0

What: Create an array that is grouped by 'ID' and 'Currency'. Accumulate currency for duplicates.

How:

  • Add rows one at a time to an output array.
  • If group is not in the array then add it
  • If it is in the array then add the currency to the existing record.

Demonstration at eval.in

Code:

/** ----------------------------------------------
* Create an output array one row at a time.
* 
* Group by Id and currency.   
* 
* @param array $groups
* 
* @return array
*/
function getCurrencyGroups(array $groups)
{
    $currencyGroups = array();

    foreach ($groups as $item) {

        $id       = $item['ID'];
        $currency = $item['currency'];
        $amount   = $item['total'];

        if (!isset($currencyGroups[$id][$currency])) {
            $currencyGroups[$id][$currency] = $amount;
        }
        else {
            $currencyGroups[$id][$currency] += $amount;
        }
    }

    return $currencyGroups;
}

Run it:

$currencyGroups = getCurrencyGroups($source);

Output:

array (size=2)
  126871 => 
    array (size=1)
      'USD' => string '200.00' (length=6)

  126872 => 
    array (size=2)
      'Euro' => float 4000
      'USD' => string '500.00' (length=6)
Edson answered 1/9, 2016 at 10:35 Comment(0)
S
0

I found myself in a similar situation except for I painted myself into a corner and needed to use the same array for input and output. I also found Manish response to be a little heavy-handed.

foreach($open_po_report as $pkey => &$po_line){
    foreach($open_po_report as $dkey => $dupe_item){
        //do not compare the exact same line
        if($dupe_item['PoNo'].$dupe_item['Line'] === $po_line['PoNo'].$po_line['Line']){
            continue;
        }
        //once you find a duplicate sum the qty to the original occurance
        if($dupe_item['ItemVendorItem'] === $po_line['ItemVendorItem']){
            $po_line['MyOrder']+=$dupe_item['MyOrder'];
            unset($open_po_report[$dkey]);
        }
        //delete the duplicate entry
    }
}
Scapula answered 14/4, 2020 at 0:5 Comment(0)
C
-1

@Cloud Try this.

$array = array(array("ID"   => "126871","total"=>"200.00","currency"=>"USD","name"=>"John",),array("ID" => "126871","total"=>"200.00","currency"=>"USD","name"=>"John",),array("ID" => "126872","total"=>"1000.00","currency"=>"Euro","name"=>"John",));
    echo "<pre>";
    print_r($array);
    $unique = array_map('unserialize', array_unique(array_map('serialize', $array)));

Sure @Magnus Eriksson. I am explaining why we use 'serialize' and 'unserialize' in steps :

Step 1: Convert the multidimensional array to one-dimensional array

To convert the multidimensional array to a one-dimensional array, first generate byte stream representation of all the elements (including nested arrays) inside the array. serialize() function can generate byte stream representation of a value. To generate byte stream representation of all the elements, call serialize() function inside array_map() function as a callback function. The result will be a one dimensional array no matter how many levels the multidimensional array has.

Step 2: Make the values unique

To make this one dimensional array unique, use array_unique() function.

Step 3: Revert it to the multidimensional array

Though the array is now unique, the values looks like byte stream representation. To revert it back to the multidimensional array, use unserialize() function.

I hope now why i make this code.

Cynic answered 1/9, 2016 at 7:53 Comment(3)
I might not understand array_map as well as I thought, but where does unserialize and serialize fit in? You should really explain what the code is actually doing, not just post some random code snippet.Hersch
i think the OP wants to sum the "total" field for the rows with the same id. I think this needs a little more parsing :(Hefter
This code is provably incorrect and will only confuse researchers. Proof: 3v4l.org/lWA8Z This destroys data, it does no summing.Lavaliere

© 2022 - 2024 — McMap. All rights reserved.