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.

2
  • It looks like JS array of objects. Commented Sep 1, 2016 at 7:46
  • " 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. Commented Sep 1, 2016 at 7:53

5 Answers 5

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;
Sign up to request clarification or add additional context in comments.

Comments

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"}
]

Comments

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)

Comments

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
    }
}

Comments

-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.

3 Comments

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.
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 :(
This code is provably incorrect and will only confuse researchers. Proof: 3v4l.org/lWA8Z This destroys data, it does no summing.

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.