How to merge array and sum up the values depending on key? - php

I have an array something like below. I want to merge the nested array and display the totals. Here ID = 60.I want to merge this [0] and [1] depending in the ID value i.e., 60.
Array(
[0] => Array
(
[ID] => 60
[TOTAL] => 500
)
[1] => Array
(
[ID] => 60
[TOTAL] => 600
)
[2] => Array
(
[ID] => 61
[TOTAL] => 600
)
)
I tried with two for loops
foreach($result as $key=>$value){
foreach($result as $key1 => $value1){
// Do stuffs here
}
}
I want the output as
Array(
[0] => Array(
[ID] =>60
[TOTAL] => 1100
)
[1] =>Array(
[ID] =>61
[TOTAL] => 600
)
)

<?php
$result = Array(
Array
(
'ID' => 60,
'TOTAL' => 500
),
Array
(
'ID' => 60,
'TOTAL' => 600
),
Array
(
'ID' => 61,
'TOTAL' => 600
)
);
$set = [];
foreach($result as $data){
if(!isset($set[$data['ID']])) $set[$data['ID']] = 0;
$set[$data['ID']] += $data['TOTAL'];
}
$result_set = [];
foreach($set as $id => $total){
$result_set[] = [
'ID' => $id,
'TOTAL' => $total
];
}
print_r($result_set);
Demo: https://3v4l.org/NMmHC
We store IDs as keys in our $set array and keep adding the total to it whenever we come across the same key in the foreach loop.
In the end, we collect the results in a new array with ID and it's respective total.

My suggestion is to use array_reduce() which iteratively reduce the array to a single value using a callback function.
$arr = [['ID' => 60,'TOTAL' => 500],['ID' => 60,'TOTAL' => 600],['ID' => 61,'TOTAL' => 600]];
$arr = array_reduce($arr, function($acc, $new) {
if (!isset($acc[$new['ID']])) {
$acc[$new['ID']] = $new;
return $acc;
}
$acc[$new['ID']]['TOTAL'] += $new['TOTAL'];
return $acc;
}, []);
echo '<pre>', print_r(array_values($arr));
Working demo.

Solution 1
$arrayvariable=Array(
[0] => Array
(
[ID] => 60
[TOTAL] => 500
)
[1] => Array
(
[ID] => 60
[TOTAL] => 600
)
[2] => Array
(
[ID] => 61
[TOTAL] => 600
)
)
$output = array_reduce($arrayvariable, function (array $compare, array $item) {
$intrestkey = $item ['ID'];
if (array_key_exists($intrestkey, $compare)) {
$compare [$intrestkey] ['TOTAL'] += $item ['TOTAL'];
} else {
$compare [$intrestkey] = $item;
}
return $compare;
}, array());
$incremetedmerged_array = array_values($output);
print_r($incremetedmerged_array); //Produces
Array(
[0] => Array(
[ID] =>60
[TOTAL] => 1100
)
[1] =>Array(
[ID] =>61
[TOTAL] => 600
)
)

Related

Get same index value of an array repeated time, based on a variable in php

We have an array in PHP like below:
Array
(
[0] => Array
(
[id] => 29
[name] => Testing1
)
[1] => Array
(
[id] => 30
[name] => Testing2
)
[2] => Array
(
[id] => 31
[name] => Testing3
)
)
We also have a variable $getvalue . We want to create a function (we will use the function in for loop) in which we pass above array and $getvalue. If $getvalue = 2 it should return key[0] 2 time, key[1] 2 time and key[2] 2 time like below.
[0] => Array
(
[id] => 29
[name] => Testing1
)
[0] => Array
(
[id] => 29
[name] => Testing1
)
[1] => Array
(
[id] => 30
[name] => Testing2
)
[1] => Array
(
[id] => 30
[name] => Testing2
)
[2] => Array
(
[id] => 31
[name] => Testing3
)
[2] => Array
(
[id] => 31
[name] => Testing3
)
If $getvalue = 1 it should return key[0] 1 time, key[1] 1 time and key[2] 1 time like below.
[0] => Array
(
[id] => 29
[name] => Testing1
)
[1] => Array
(
[id] => 30
[name] => Testing2
)
[2] => Array
(
[id] => 31
[name] => Testing3
)
Tried :
for($i = 0; $i<=count($array); $i++) {
foreach($array as $key => $val) {
if($i==$getvalue )
{
$a[] = $array[$i+1];
}
else
{
$a[] = $array[$i];
}
}
}
Also tried :
static function abc ($array,$getvalue)
{
foreach ($array as $key => $value) {
for ($i=0; $i <= $getvalue; $i++) {
return $arr[$i];
}
}
}
Each element of input array is added to the return value $getvalue times:
<?php
function repeatify( array $array, int $getvalue ): array {
$out = [];
if($getvalue <= 0) return $out;
foreach( $array as $element ){
foreach( range(0, $getvalue - 1) as $we_actualy_are_not_using_this_var )
$out[] = $element;
# Or alternatively with a `for` loop (i'll comment this out since i prefer an above code):
/*
for (
$we_actualy_are_not_using_this_var = 0;
$we_actualy_are_not_using_this_var < $getvalue;
$we_actualy_are_not_using_this_var++
) {
$out[] = $element;
}
*/
}
return $out;
}
$data = [
[
'id' => 29,
'name' => 'Testing1',
],
[
'id' => 30,
'name' => 'Testing2',
],
[
'id' => 31,
'name' => 'Testing2',
],
];
print '<pre>';
print_r( repeatify( $data, 0 ) );
print_r( repeatify( $data, 1 ) );
print_r( repeatify( $data, 2 ) );

Group subsets of data in 3-level array by identifying column

I've this type of array in PHP:
Array(
[100] => Array(
[1] => Array (
[AVA_Date] => 2019-04-18
[ROO_Id] => 100
[RAT_Id] => 9
)
[2] => Array (
[AVA_Date] => 2019-04-20
[ROO_Id] => 100
[RAT_Id] => 10
)
[4] => Array (
[AVA_Date] => 2019-04-21
[ROO_Id] => 100
[RAT_Id] => 10
)
[7] => Array (
[AVA_Date] => 2019-04-22
[ROO_Id] => 100
[RAT_Id] => 9
)
)
)
I would like to merge items on ROO_Id and RAT_Id.
Then, for the AVA_Date, I need to list them under a new array in the current array.
So, the desired output is:
Array(
[100] => Array(
[0] => Array (
[AVA_Date] => Array (
[0] => 2019-04-18
[1] => 2019-04-22
)
[ROO_Id] => 100
[RAT_Id] => 9
)
[1] => Array (
[AVA_Date] => Array (
[0] => 2019-04-20
[1] => 2019-04-21
)
[ROO_Id] => 100
[RAT_Id] => 10
)
)
)
Here what I have tried:
$newArrOtherRooms = array_reduce($newArr, function($acc, $val) {
$room = array_search($val['ROO_Id'], array_column($acc, 'ROO_Id'));
$rate = array_search($val['RAT_Id'], array_column($acc, 'RAT_Id'));
if($rate == $room && $room > -1) {
array_push($acc[$room]['AVA_Date'], $val['AVA_Date']);
}
else {
$new_arr = $val;
$new_arr['AVA_Date'] = [$val['AVA_Date']];
array_push($acc, $new_arr);
}
return $acc;
},[]);
But it doesn't work like I want.
There are a couple of issues with your code. Firstly, you need to wrap the array_reduce with a foreach over the outer level of $newArr. Secondly, your call to array_search doesn't consider the fact that a ROO_Id or RAT_Id value might exist more than once in the array, as it only returns the first key at which it finds the value. To work around this, you can use array_keys to get an array of key values for each ROO_Id and RAT_Id value, and then take the intersection of those two arrays using array_intersect to see if both are present in the same element. If so, you update that element, otherwise you create a new one:
foreach ($newArr as $key => $array) {
$newArrOtherRooms[$key] = array_reduce($array, function($acc, $val) {
$room = array_keys(array_column($acc, 'ROO_Id'), $val['ROO_Id']);
$rate = array_keys(array_column($acc, 'RAT_Id'), $val['RAT_Id']);
$common = array_intersect($room, $rate);
if(!empty($common)) {
array_push($acc[current($common)]['AVA_Date'], $val['AVA_Date']);
}
else {
$new_arr = $val;
$new_arr['AVA_Date'] = [$val['AVA_Date']];
array_push($acc, $new_arr);
}
return $acc;
},[]);
}
print_r($newArrOtherRooms);
Output:
Array(
[100] => Array(
[0] => Array (
[AVA_Date] => Array (
[0] => 2019-04-18
[1] => 2019-04-22
)
[ROO_Id] => 100
[RAT_Id] => 9
)
[1] => Array (
[AVA_Date] => Array (
[0] => 2019-04-20
[1] => 2019-04-21
)
[ROO_Id] => 100
[RAT_Id] => 10
)
)
)
Demo on 3v4l.org
There is absolutely no reason to be making all of those iterated function calls.
Use a nested loop to iterate the subset of data for each room, group on the room "rate id", and push all "available date" values into a subarray in the respective group. When the subset of data is fully iterated, push its grouped data into the result array.
Code: (Demo)
$result = [];
foreach ($newArr as $rooId => $rows) {
$groups = [];
foreach ($rows as $row) {
if (!isset($groups[$row['RAT_Id']])) {
$row['AVA_Date'] = (array) $row['AVA_Date'];
$groups[$row['RAT_Id']] = $row;
} else {
$groups[$row['RAT_Id']]['AVA_Date'][] = $row['AVA_Date'];
}
}
$result[$rooId] = array_values($groups);
}
var_export($result);
Output:
array (
100 =>
array (
0 =>
array (
'AVA_Date' =>
array (
0 => '2019-04-18',
1 => '2019-04-22',
),
'ROO_Id' => 100,
'RAT_Id' => 9,
),
1 =>
array (
'AVA_Date' =>
array (
0 => '2019-04-20',
1 => '2019-04-21',
),
'ROO_Id' => 100,
'RAT_Id' => 10,
),
),
)

How to prepare a new array out of two arrays inside foreach loop?

I am trying to compare the keys of an array with values of another array. In case of greater values of the current key, I would like to push the value into a new array. Then I want to insert all the collected values for that specific key into a DB table.
These are my input arrays:
$productlist = [result] => Array
(
[0] => Array
(
[configoption1] => 2M
[id] => 96
)
[1] => Array
(
[configoption1] => 5M
[id] => 97
)
[2] => Array
(
[configoption1] => 15M
[id] => 98
)
[3] => Array
(
[configoption1] => 30M
[id] => 99
)
)
$myplans = Array
(
[2M] => Array
(
[price] => 10
)
[5M] => Array
(
[price] => 10
)
[15M] => Array
(
[price] => 10
)
[30M] => Array
(
[price] => 10
)
)
The following is my sample code:
$upgradelist = array()
foreach ($myplans as $plan => $data) {
foreach($productlist['result'] as $key=>$value){
if($plan == 'ENTERPRISE'){
//no higher plans than Enterprise
}else{
$plan1 = (int)substr_replace($plan, "", -1);
$value['configoption1'] = (int)substr_replace($value['configoption1'], "", -1);
#echo " configconfig=> ".$value['configoption1'];
if($plan > $value['configoption1']){
$upgrade_product_ids[$plan][] = $value['id'];
}
}
}
//insert upgrade products list
if(!empty($upgradelist)){
foreach($upgradelist as $key => $upgrade_product_id){
#$insert_stmt_upgradeproduct = <insert statement> for each $plan
}
}
}
expected output each time I come out from the foreach loop: > foreach($productlist['result']
$upgradelist = Array
(
[2] => Array
(
[0] => 97 //5M
[1] => 98 //15M
[2] => 99 //30M
)
)
$upgradelist = Array
(
[5] => Array
(
[0] => 98
[1] => 99
)
)
$upgradelist = Array
(
[15] => Array
(
[0] => 99
)
)
$upgradelist = Array
(
[30] => Array
(
)
)
You can solve like below:
foreach($myplans as $key => $plan) {
$data_to_be_inserted = [];
foreach($productlist['result'] as $product) {
if ($key > $product['configoption1']) {
$data_to_be_inserted [] = $product['id'];
}
}
if (count($data_to_be_inserted)) {
//insert into database(expected value will be available here)
}
}
YOu can do like this
<?php
$myArray = [];
$myArray['result'] = array(
array("configoption1" => "2m", "id" => 96),
array("configoption1" => "5m", "id" => 97),
array("configoption1" => "15m", "id" => 98),
array("configoption1" => "30m", "id" => 99)
);
//print_r($myArray);
$myArray2 =[
"2m" => ["price" => 10],
"5m" => ["price" => 10],
"15m" => ["price" => 10],
"30m" => ["price" => 10]
];
$resultArray = [];
foreach($myArray2 as $key => $values) {
$keyNum = (int)$key;
$newTempArray[$keyNum] = [];
foreach($myArray['result'] as $newresult) {
$configoption1Num = (int)$newresult['configoption1'];
if($configoption1Num > $keyNum) {
array_push($newTempArray[$keyNum], $newresult['id']);
}
}
print_r($newTempArray[$keyNum]);
echo "<br>";
}
http://sandbox.onlinephpfunctions.com/code/008c839fb4fad4ed2aceae7c4ed1220579e8e318

how to calculate sum of total key in same array

i need to calculate the total key within the following array that contains 4 different sub arrays
Array
(
[0] => Array
(
[total] => 4.2
[sku] => 4321
)
[1] => Array
(
[total] => 2
[sku] => 2456
)
[2] => Array
(
[total] => 3
[sku] => 2245
)
[3] => Array
(
[total] => 1.5
[sku] => 2674
)
)
i was calculating it using mysql directly but i prefer to use php
$sql = "SELECT SUM(CAST(IFNULL(total,0) AS DECIMAL(10,2))) FROM trans WHERE trans.userid = :userid";
so total has to be in the same format as from the query
10.70
You can loop over the array, adding up as you go, and then formatting with number_format(), or use array_column() to extract the 'total', and use array_sum() to add them, and again, using number_format() or sprintf() to format them.
echo number_format(array_sum(array_column($array, 'total')), 2);
I guess something like this:-
$array = Array
(
[0] => Array
(
[total] => 4.2
[sku] => 4321
)
[1] => Array
(
[total] => 2
[sku] => 2456
)
[2] => Array
(
[total] => 3
[sku] => 2245
)
[3] => Array
(
[total] => 1.5
[sku] => 2674
)
);
$total = 0;
foreach ($array as $key => $value) {
$total += $value['total'];
}
print_r($total);
you can iterate your array and sum all values like:
<?php
$array = array(
array(
'total' => 4.2,
'sku' => 4321
),
array(
'total' => 2,
'sku' => 2456
),
array(
'total' => 3,
'sku' => 2245
),
array(
'total' => 1.5,
'sku' => 2674
),
);
$result = array('total' => 0,'sku' => 0);
foreach($array as $key => $value) {
$result['total'] += $value['total'];
$result['sku'] += $value['sku'];
}
var_dump($result);
Result: array(2) { ["total"]=> float(10.7) ["sku"]=> int(11696) }
for single total sum output:
echo $result['total'];
You can also try with array_walk_recursive() like this https://eval.in/875555
$input = [your_2d_array_goes_here];
$final = array();
array_walk_recursive($input, function($item, $key) use (&$final){
$final[$key] = isset($final[$key]) ? $item + $final[$key] : $item;
});
print '<pre>';
print_r($final);
print '</pre>';
print $final['total'];
?>

PHP - merging 2D array by keys

How can I merge these array together?
Array
(
[0] => Array
(
[type] => Person
[relevance] => 0.700000
[count] => 300
[text] => Chris
)
)
Array
(
[0] => Array
(
[type] => Person
[relevance] => 0.900000
[count] => 400
[text] => Chris
)
[1] => Array
(
[type] => Person
[relevance] => 0.500000
[count] => 200
[text] => Tom
)
)
or array like this:
Array
(
[0] => Array
(
[type] => Person
[relevance] => 0.700000
[count] => 300
[text] => Chris
)
[1] => Array
(
[type] => Person
[relevance] => 0.900000
[count] => 400
[text] => Chris
)
[2] => Array
(
[type] => Person
[relevance] => 0.500000
[count] => 200
[text] => Tom
)
)
The expected result is:
Array
(
[0] => Array
(
[type] => Person
[relevance] => 0.800000
[count] => 700
[text] => Chris
)
[1] => Array
(
[type] => Person
[relevance] => 0.500000
[count] => 200
[text] => Tom
)
)
[relevance] value is an average number
[count] value is an incremental number
The merging of these array should base on [text] value.
How can I do this with php in a fast way?
Thanks for helping.
If this is the array
$array = Array(
Array(
'type' => 'Person',
'relevance' => .7,
'count' => 300,
'text' => 'Chris'
),
Array(
'type' => 'Person',
'relevance' => .9,
'count' => 400,
'text' => 'Chris'
),
Array(
'type' => 'Person',
'relevance' => .5,
'count' => 200,
'text' => 'Tom'
),
);
then:
$tmp = Array();
foreach($array as $obj) {
if(!isset($tmp[$obj['text']])) {
$tmp[$obj['text']] = array_merge(Array('total_count'=>1),$obj);
continue;
}
$tmp[$obj['text']]['count'] += $obj['count'];
$tmp[$obj['text']]['relevance'] += $obj['relevance'];
$tmp[$obj['text']]['total_count']++; // useful for average calculation
}
$result = Array();
foreach($tmp as $key=>$obj) {
$obj['relevance'] = $obj['relevance']/$obj['total_count'];
unset($obj['total_count']); // useless now
$result[] = $obj;
}
print_r($result);
Something like this maybe:
$newArray = array();
foreach ($oldArray as $item) {
if (!array_key_exists($item['text'], $newArray)) {
$newArray[$item['text']] = $item;
$newArray[$item['relevance_values']] = array();
} else {
$newArray[$item['text']]['count'] += $item['count'];
$newArray[$item['relevance_values']][] = $item['relevance'];
}
}
foreach ($newArray as $item) {
$relevance = 0;
foreach ($item['relevance_values'] as $value) {
$relevance += $value;
}
$item['relevance'] = $relevance / count($item['relevance_values']);
}
Try this:
function mergeOnText($array){
$results = array();
foreach($array as $person){
$found = -1;
foreach($results as $i => $res)
if($res['text'] == $person['text']){
$found = $i;
break;
}
if($found > -1){
$results[$found]['relevance'][] = $person['relevance'];
$results[$found]['count'] += $person['count'];
} else {
$results[] = $person;
}
}
foreach($results as $i => $res)
$results[$i]['relevance'] = array_sum($res['relevance']) / count($res['relevance']);
return $results;
}

Categories