This question already has answers here:
Associative array, sum values of the same key
(5 answers)
Closed 2 years ago.
I want to sum an array and grouping them by its key value.
this is the array :
Array
(
[0] => Array
(
[delivery_plan] => 80::2020/07
[additional_amount_usd] => 32.88
)
[1] => Array
(
[delivery_plan] => 80::2020/09
[additional_amount_usd] => 16.44
)
[2] => Array
(
[delivery_plan] => 80::2020/07
[additional_amount_usd] => 32.88
)
)
I want output to be like this :
Array
(
[0] => Array
(
[delivery_plan] => 80::2020/07
[additional_amount_usd] => 65.76
)
[1] => Array
(
[delivery_plan] => 80::2020/09
[additional_amount_usd] => 16.44
)
I have tried using this code, but the output different from my expected result :
$arr = [];
foreach ($section_balance as $sb => $val) {
if(array_key_exists($sb, $arr)){
$arr[$sb] += array_sum($val);
} else {
$arr[$sb] = array_sum($val);
}
}
i've got tis result instead :
Array
(
[0] => 112.88
[1] => 96.44
[2] => 112.88
)
How can i solve this ?
This is one way to do it breaking it down into steps...
1.Create the Array that sums the matching delivery_plans
2.Rebuild the Array as required
<?php
$sum_array = [];
foreach($array as $item) {
if (key_exists($item['delivery_plan'], $sum_array)) {
$sum_array[$item['delivery_plan']] += $item['additional_amount_usd'];
} else {
$sum_array[$item['delivery_plan']] = $item['additional_amount_usd'];
}
}
$final_array = [];
foreach($sum_array as $key => $value) {
$final_array[] = ['delivery_plan' => $key, 'additional_amount_usd' => $value];
}
Refactoring the above so the code is not dependant upon hardcoded index names...
$key_name = 'delivery_plan';
$value_name = 'additional_amount_usd';
$sum_array = [];
foreach($array as $item) {
if (key_exists($item[$key_name], $sum_array)) {
$sum_array[$item[$key_name]] += $item[$value_name];
} else {
$sum_array[$item[$key_name]] = $item[$value_name];
}
}
$final_array = [];
foreach($sum_array as $key => $value) {
$final_array[] = [$key_name => $key, $value_name => $value];
}
And you could then turn that into a function if you so desired...
The result is (using var_dump())
array(2) {
[0]=>
array(2) {
["delivery_plan"]=>
string(13) "80::2020 / 07"
["additional_amount_usd"]=>
float(65.76)
}
[1]=>
array(2) {
["delivery_plan"]=>
string(13) "80::2020 / 09"
["additional_amount_usd"]=>
float(16.44)
}
}
Update:
Also Take a look at the solution provided by Kevin.
3v4l.org/h9Q5L
Related
I have this problem. I have a multidimensional json array (don't ask - legacy code). I convert it to PHP array. I need to extract all KEYS that have EQUAL VALUE (in my case "666"). I need each key to be assign to a SEPARATE variable. In my code I succeeded to fetch the keys but I can assign them only to another array or all at once to a single variable. Please HELP!!!
Love V
Here is the code:
<?php
//user input
$in = "666";
$outputZ = '[
{"record_id_001":"1"},
{"record_id_002":"13"},
{"record_id_003":"666"},
{"record_id_004":"72661781"},
{"record_id_005":"8762"},
{"record_id_006":"666"},
{"record_id_007":"8762"},
{"record_id_008":"666"},
{"record_id_009":"8762"},
{"record_id_010":"8762"},
{"record_id_011":"666"}
]';
//convert json to php array
//someArray = json_decode($someJSON, true);
$decoZ = json_decode($outputZ, true);
// TESTING (move to comment latter)
//print_r ($decoZ);
//loop through each array an check for user input
//way 1: assign to new array
foreach($decoZ as $array => $number)
foreach($number as $key => $value)
if (in_array("$in", $number)) {
$var = $key;
$getarray = "'" . $var . "'";
$recnumber = array($getarray);
print_r ($recnumber);
}
//way 2: assign to variable
foreach($decoZ as $array => $number)
foreach($number as $key => $value)
if (in_array("$in", $number)) {
$var = $key;
echo "$var" . " ";
}
?>
You're overwritting your array on each iterations $recnumber = array($getarray);
I would rather follow this logic :
<?php
//user input
$in = "666";
$outputZ = '[
{"record_id_001":"1"},
{"record_id_002":"13"},
{"record_id_003":"666"},
{"record_id_004":"72661781"},
{"record_id_005":"8762"},
{"record_id_006":"666"},
{"record_id_007":"8762"},
{"record_id_008":"666"},
{"record_id_009":"8762"},
{"record_id_010":"8762"},
{"record_id_011":"666"}
]';
$decoZ = json_decode($outputZ, true);
// create empty array
$recnumber = [];
foreach($decoZ as $record)
{
foreach($record as $key => $value)
{
// simply compare input with current value
if ($value === $in)
{
// add the key to the previously created array
$recnumber[] = $key;
}
}
}
var_dump($recnumber);
This outputs :
array(4) {
[0]=>
string(13) "record_id_003"
[1]=>
string(13) "record_id_006"
[2]=>
string(13) "record_id_008"
[3]=>
string(13) "record_id_011"
}
You can simply remap the records.
At the end you can grab them like
$codes666 = $ids['666'];
$outputZ = '[
{"record_id_001":"1"},
{"record_id_002":"13"},
{"record_id_003":"666"},
{"record_id_004":"72661781"},
{"record_id_005":"8762"},
{"record_id_006":"666"},
{"record_id_007":"8762"},
{"record_id_008":"666"},
{"record_id_009":"8762"},
{"record_id_010":"8762"},
{"record_id_011":"666"}
]';
$records = json_decode($outputZ);
$ids = [];
foreach($records as $record) {
foreach($record as $key => $value) {
$ids[(string)$value][] = $key;
}
}
print_r($ids);
Gives
Array
(
[1] => Array
(
[0] => record_id_001
)
[13] => Array
(
[0] => record_id_002
)
[666] => Array
(
[0] => record_id_003
[1] => record_id_006
[2] => record_id_008
[3] => record_id_011
)
[72661781] => Array
(
[0] => record_id_004
)
[8762] => Array
(
[0] => record_id_005
[1] => record_id_007
[2] => record_id_009
[3] => record_id_010
)
)
for a long time can't resolve smth looking like as very simple matter... I want merge a two dimensional arrays.
The example:
$arr1 = {
[532] =
{
[0] = "11"
[1] = "12"
}
[273] =
{
[0] = "99"
}
}
$arr2 = {
[532] =
{
[0] = "11"
[1] = "13"
}
}
And the result of merging should be, a map on common keys, exactly like that array:
$result = {
[532] =
{
[0] =
{
[0] = "11"
[1] = "12"
}
[1] =
{
[0] = "11"
[1] = "13"
}
}
[273]
[0] =
{
[0] = "99"
}
[1] =
{
}
}
I try sometihng like that:
$result = $arr1;
foreach ($arr2 as $key => $value) {
$result[$key] = isset($result[$key]) ? array_merge([$result[$key]], [$value]) : [$value];
}
But it doesnt work if $arr2 is empty :(
For the second array checking, you need to use isset() either array set or not:
Example:
<?php
$arr1 = array('532'=>array('11','12'),'273'=>array('99'));
$arr2 = array('532'=>array('11','13'));
$newArr = array();
foreach ($arr1 as $key => $value) {
if(isset($arr2[$key])){
$newArr[$key][] = $value;
$newArr[$key][] = $arr2[$key];
}
else{
$newArr[$key] = $value;
}
}
echo "<pre>";
print_r($newArr);
?>
Result:
Array
(
[532] => Array
(
[0] => Array
(
[0] => 11
[1] => 12
)
[1] => Array
(
[0] => 11
[1] => 13
)
)
[273] => Array
(
[0] => 99
)
)
Further more, if you want to merge both same index than you can use array_merge() some thing like that:
<?php
$arr1 = array('532'=>array('11','12'),'273'=>array('99'));
$arr2 = array('532'=>array('11','13'));
$newArr = array();
foreach ($arr1 as $key => $value) {
if(isset($arr2[$key])){
$newArr[$key][] = array_merge($value,$arr2[$key]);
}
else{
$newArr[$key] = $value;
}
}
echo "<pre>";
print_r($newArr);
?>
Result:
Array
(
[532] => Array
(
[0] => Array
(
[0] => 11
[1] => 12
[2] => 11
[3] => 13
)
)
[273] => Array
(
[0] => 99
)
)
Note that, ist script, will give you result as you need with unique index.
Second script will give you all values in one single array.
Probably something like this
$arr1 = {
[532] =
{
[0] = "11"
[1] = "12"
}
[273] =
{
[0] = "99"
}
}
$arr2 = {
[532] =
{
[0] = "11"
[1] = "13"
}
}
$newarray = array();
foreach ($arr1 as $key => $value) {
$cu = $arr1[$key];
$newarray[$key][] = $cu;
if(!isset($arr2[$key])) {
$newarray[$key][] = array();
}
else {
$newarray[$key][] = $arr2[$key];
}
}
foreach ($arr2 as $key => $value) {
if(!isset($newarray[$key])) {
$newarray[$key][] = $arr2[$key];
}
}
I have to arrays I would like to compare:
$original and $duplicate.
for example here is my original file:
print_r($original);
Array ( [0] => cat423 [1] => dog456 [2] => horse872 [3] => duck082 )
and here is my duplicate:
print_r($dublicate);
Array ( [0] => cat423 [1] => dug356 )
I compare them with array_diff:
$result = array_diff($original, $dublicate);
My result:
Array ( [1] => dog456 [2] => horse872 [3] => duck082 )
So far so good, but I need to make a difference between the values which are incorrect and the values which are completely missing. Is this possible?
A way would be to crawl the entire original array, afterwards you will have two arrays, missings and duplicates.
$original = array("cat423", "dog456", "horse872", "duck082");
$duplicate = array("cat423", "dug356");
$missings = $duplicates = array();
foreach ($original as $val) {
if (in_array($val, $duplicate))
$duplicates[] = $val;
else
$missings[] = $val;
}
If you need the keys as well, you would have to alter the foreach loop like so:
foreach ($original as $key=>$val) {
if (in_array($val, $duplicate))
$duplicates[] = array("key" => $key, "value" => $val);
else
$missings[] = array("key" => $key, "value" => $val);
}
use in_array function
$original = array("cat423", "dog456", "horse872", "duck082");
$duplicate = array("cat423", "dug356");
foreach ($original as $item) {
if(in_array($item, $duplicate))
{
$dup[] = $item;
}
else
{
$miss[] = $item;
}
}
print_r($miss); #Array ( [0] => dog456 [1] => horse872 [2] => duck082 )
print_r($dup); #Array ( [0] => cat423 )
Working Preview
I Have an array in PHP that looks like:
Array ( [2099:360] => 6-3.25 [2130:361] => 4-2.5 [2099:362] => 14-8.75 )
Notice there is Two Keys that are 2099 and one that is 2130. I Have a foreach to remove the everything after the colon. the $drop is my array
$a = array();
foreach ($drop as $part=>$drop_a){
$ex_part = explode(":", $part);
$a[$ex_part[0]] = $drop_a;
}
print_r($a);
but when I print $a it displays only the recent value of the 2099?
Array ( [2099] => 14-8.75 [2130] => 4-2.5 )
Any Successions? How can I get it to display all of the values?
Thank You for Your Help
One solution is to use a multi-dimensional array to store this strategy:
$a = array();
foreach ($drop as $part=>$drop_a){
$ex_part = explode(":", $part);
if (isset($a[$ex_part[0]])) {
$a[$ex_part[0]][] = $drop_a;
} else {
$a[$ex_part[0]] = array($drop_a);
}
}
Your resulting data-set will however be different:
Array ( [2099] => Array ( [0] => 6-3.25 [1] => 14-8.75) [2130] => Array ( [0] => 4-2.5 ) )
It may be beneficial to you to preserve the second portion after the colon :
$a = array();
foreach ($drop as $part=>$drop_a){
$ex_part = explode(":", $part);
if (isset($a[$ex_part[0]])) {
$a[$ex_part[0]][$ex_part[1]] = $drop_a;
} else {
$a[$ex_part[0]] = array($ex_part[1] => $drop_a);
}
}
Now your result is a little more meaningful:
Array ( [2099] => Array ( [360] => 6-3.25 [362] => 14-8.75) [2130] => Array ( [361] => 4-2.5 ) )
Finally you can use alternative key-naming strategy if one is already occupied:
$a = array();
foreach ($drop as $part=>$drop_a){
$ex_part = explode(":", $part);
if (isset($a[$ex_part[0]])) {
$a[altName($ex_part[0], $a)] = $drop_a;
} else {
$a[$ex_part[0]] = $drop_a;
}
}
function altName($key, $array) {
$key++; // Or however you want to do an alternative naming strategy
if (isset($array[$key])) {
return altName($key, $array); // This will eventually resolve - but be careful with the recursion
}
return $key;
}
Returns:
Array
(
[2099] => 6-3.25
[2130] => 4-2.5
[2100] => 14-8.75
)
You basically have a key and a sub key for each entry, so just put them in a multidimensional array:
$a = array();
foreach ($drop as $key => $val) {
list($key, $subKey) = explode(':', $key);
$a[$key][$subKey] = $val;
}
Gives you:
Array
(
[2099] => Array
(
[360] => 6-3.25
[362] => 14-8.75
)
[2130] => Array
(
[361] => 4-2.5
)
)
You can traverse multidimensional arrays by nesting loops:
foreach ($a as $key => $subKeys) {
foreach ($subKeys as $subKey => $val) {
echo "$key contains $subKey (value of $val) <br>";
}
}
I have an array like this;
Array
(
[database1.table1.fieldname] => "test"
[database1.table1.fieldname1] => "test1"
[database2.table2.fieldname] => "test2"
)
Here for the first two values the database name and table name are the same. Fieldname is not so important here. For the third value the database name and table name are different. What I want to achieve is that I want to split this array in to seperate arrays by comparing the database name and table name. I need to achieve something like this;
Array
(
[database1.table1.fieldname] => "test"
[database1.table1.fieldname1] => "test1"
)
Array
(
[database2.table2.fieldname] => "test2"
)
Is it possible to do something like this?.
Try like
foreach($my_arr as $key=>$value) {
$new_key = explode('.',$key);
if($new_key[0] == "datebase1" && $new_key[1] == "table1") {
$arr1[$key] = $value;
} elseif ($new_key[0] == "datebase2" && $new_key[1] == "table2") {
$arr2[$key] = $value;
}
}
Or you can try like
foreach($my_arr as $key=>$value) {
$new_key = explode('.',$key);
$new_arr[$new_key[0]][$new_key[1]][] = array($key=>$value);
}
print_r($new_arr);
Output :
Array
(
[database1] => Array
(
[table1] => Array
(
[0] => Array
(
[database1.table1.fieldname] => test
)
[1] => Array
(
[database1.table1.fieldname1] => test1
)
)
)
[database2] => Array
(
[table2] => Array
(
[0] => Array
(
[database2.table2.fieldname] => test3
)
)
)
)
Here it is. Take it.
function splitDatabaseArray($array)
{
ksort($array);
$return = array();
$last_database_table = array();
foreach ($array as $index => $value)
{
$database_table = array();
list($database_table[0], $database_table[1]) = explode('.', $index);
if ($last_database_table != $database_table)
$row = &$return[];
$last_database_table = $database_table;
$row[$index] = $value;
}
return $return;
}
$array = array
(
'database1.table1.fieldname' => "test",
'database1.table1.fieldname1' => "test1",
'database2.table2.fieldname' => "test2");
var_dump(splitDatabaseArray($array));
http://3v4l.org/TC542