php array sum key where value is same - php

I have an array that contains a sub-array. I want to sum the values where the key is the same and to make it in one list.
Here is my array:
$array = array( array(x1=> 1, x2 => 3, y5 => 9),
array(x1=> 3, x4 => 1, y5 => 1),
array(x1=> 1, x8 => 5, a5 => 2),
array(x1=> 2, x10 => 3)
);
And I want to have an array like :
$newarray = array(x1=>7 , x2 => 3, x4=>1, x8=>5, x10=> 3, y5=>9, y5=>1, a5=>2));
some try:
foreach($array as $key => $values)
{
foreach($values as $n_k => $n_v)
{
$newarray [$n_k] += $n_v;
}
}

The problem is you are adding a value even if it is not defined.
You can check if not set by and init the value to 0
if ( !isset($newarray[$n_k]) ) $newarray[$n_k] = 0;
Here is the complete code:
$array = array( array('x1'=> 1, 'x2' => 3, 'y5' => 9), array('x1'=> 3, 'x4' => 1, 'y5' => 1), array('x1'=> 1, 'x8' => 5, 'a5' => 2), array('x1'=> 2, 'x10' => 3, 'b5' => 5));
$newarray = array();
foreach($array as $key => $values){
foreach($values as $n_k => $n_v) {
if ( !isset($newarray[$n_k]) ) $newarray[$n_k] = 0;
$newarray[$n_k] += $n_v;
}
}
This will result to:
Array
(
[x1] => 7
[x2] => 3
[y5] => 10
[x4] => 1
[x8] => 5
[a5] => 2
[x10] => 3
[b5] => 5
)

You can first get all the keys from the array and use that in a array_column and array_sum to get your desired output.
This will probably have more benefit if the array is larger.
$array = array( array("x1" => 1, "x2" => 3, "y5" => 9),
array("x1" => 3, "x4" => 1, "y5" => 1),
array("x1" => 1, "x8" => 5, "a5" => 2),
array("x1" => 2, "x10" => 3, "b5" => 5)
);
$keys = [];
// get all keys used in $array
foreach($array as $subarr){
$keys = array_merge($keys, array_keys($subarr));
}
// $keys is now:
// array (0 => 'x1', 1 => 'x2', 2 => 'y5', 3 => 'x1', 4 => 'x4', 5 => 'y5', 6 => 'x1', 7 => 'x8', 8 => 'a5', 9 => 'x1', 10 => 'x10', 11 => 'b5')
// loop only unique keys and sum the values
foreach(array_unique($keys) as $item){
$res[$item] = array_sum(array_column($array, $item));
}
var_dump($res);
https://3v4l.org/WaqlG

That's not my question, but i've found this that can help you:
https://stackoverflow.com/a/14196064/9721446
You have to create a new array, and then for each equal keyid, you're going to add the value. Somethinkg like that i think it works.
if doesn't help you, take a look at this post, that's not mine too!!!!
Associative array, sum values of the same key

<?php
$input = array( array(x1=> 1, x2 => 3, y5 => 9),
array(x1=> 3, x4 => 1, y5 => 1),
array(x1=> 1, x8 => 5, a5 => 2),
array(x1=> 2, x10 => 3)
);
$final = array();
array_walk_recursive($input, function($item, $key) use (&$final){
$final[$key] = isset($final[$key]) ? $item + $final[$key] : $item;
});
print_r($final);
?>

Related

Add up the array values based on the same key (PHP)

I found a case where I had to add values based on the same week.
[{"week":"30","nilai":"230"},{"week":"30","nilai":"66"},{"week":"29","nilai":"72"},{"week":"29","nilai":"225"},{"week":"28","nilai":"213"},{"week":"28","nilai":"72"},{"week":"27","nilai":"191"},{"week":"27","nilai":"60"},{"week":"26","nilai":"176"},{"week":"26","nilai":"65"},{"week":"25","nilai":"167"},{"week":"25","nilai":"57"},{"week":"24","nilai":"209"},{"week":"24","nilai":"62"},{"week":"23","nilai":"180"},{"week":"23","nilai":"88"},{"week":"22","nilai":"178"},{"week":"22","nilai":"72"},{"week":"21","nilai":"164"},{"week":"21","nilai":"42"},{"week":"20","nilai":"193"},{"week":"20","nilai":"50"},{"week":"19","nilai":"186"},{"week":"19","nilai":"56"}]
the results I expect among others are like this
week => 30,
nilai=> 296
<?php
$input = '[{"week":"30","nilai":"230"},{"week":"30","nilai":"66"},{"week":"29","nilai":"72"},{"week":"29","nilai":"225"},{"week":"28","nilai":"213"},{"week":"28","nilai":"72"},{"week":"27","nilai":"191"},{"week":"27","nilai":"60"},{"week":"26","nilai":"176"},{"week":"26","nilai":"65"},{"week":"25","nilai":"167"},{"week":"25","nilai":"57"},{"week":"24","nilai":"209"},{"week":"24","nilai":"62"},{"week":"23","nilai":"180"},{"week":"23","nilai":"88"},{"week":"22","nilai":"178"},{"week":"22","nilai":"72"},{"week":"21","nilai":"164"},{"week":"21","nilai":"42"},{"week":"20","nilai":"193"},{"week":"20","nilai":"50"},{"week":"19","nilai":"186"},{"week":"19","nilai":"56"}]';
$input = json_decode($input, true);
$outArr = [];
foreach ($input as $arr) {
$week = $arr['week'];
if (key_exists($week, $outArr)) {
$outArr[$week] += $arr['nilai'];
} else {
$outArr[$week] = $arr['nilai'];
}
}
//optional sort - you may remove it
ksort($outArr);
$outArr2 = [];
foreach($outArr as $week => $nilai) {
$outArr2[] = ['week' => $week, 'nilai' => $nilai];
}
var_export($outArr2);
gives result:
array (
0 =>
array (
'week' => 19,
'nilai' => 242,
),
1 =>
array (
'week' => 20,
'nilai' => 243,
),
2 =>
array (
'week' => 21,
'nilai' => 206,
),
3 =>
array (
'week' => 22,
'nilai' => 250,
),
4 =>
array (
'week' => 23,
'nilai' => 268,
),
5 =>
array (
'week' => 24,
'nilai' => 271,
),
6 =>
array (
'week' => 25,
'nilai' => 224,
),
7 =>
array (
'week' => 26,
'nilai' => 241,
),
8 =>
array (
'week' => 27,
'nilai' => 251,
),
9 =>
array (
'week' => 28,
'nilai' => 285,
),
10 =>
array (
'week' => 29,
'nilai' => 297,
),
11 =>
array (
'week' => 30,
'nilai' => 296,
),
)
<?php
$input = '[{"week":"30","nilai":"230"},{"week":"30","nilai":"66"},{"week":"29","nilai":"72"},{"week":"29","nilai":"225"},{"week":"28","nilai":"213"},{"week":"28","nilai":"72"},{"week":"27","nilai":"191"},{"week":"27","nilai":"60"},{"week":"26","nilai":"176"},{"week":"26","nilai":"65"},{"week":"25","nilai":"167"},{"week":"25","nilai":"57"},{"week":"24","nilai":"209"},{"week":"24","nilai":"62"},{"week":"23","nilai":"180"},{"week":"23","nilai":"88"},{"week":"22","nilai":"178"},{"week":"22","nilai":"72"},{"week":"21","nilai":"164"},{"week":"21","nilai":"42"},{"week":"20","nilai":"193"},{"week":"20","nilai":"50"},{"week":"19","nilai":"186"},{"week":"19","nilai":"56"}]';
$input = json_decode($input, true);
$outArr = [];
foreach ($input as $arr) {
$week = $arr['week'];
if (key_exists($week, $outArr)) {
$outArr[$week]['week'] += $arr['nilai'];
} else {
$outArr[$week]['nilai'] = $arr['nilai'];
}
}
print_r($outArr);
?>
You can do that in a single loop using array_reduce.
This solution performs a true single pass without performing any additional searches in the array. I haven't benchmarked it, but I assume it is more performant.
<?php
$values = json_decode('[{"week":"30","nilai":"230"},{"week":"30","nilai":"66"},{"week":"29","nilai":"72"},{"week":"29","nilai":"225"},{"week":"28","nilai":"213"},{"week":"28","nilai":"72"},{"week":"27","nilai":"191"},{"week":"27","nilai":"60"},{"week":"26","nilai":"176"},{"week":"26","nilai":"65"},{"week":"25","nilai":"167"},{"week":"25","nilai":"57"},{"week":"24","nilai":"209"},{"week":"24","nilai":"62"},{"week":"23","nilai":"180"},{"week":"23","nilai":"88"},{"week":"22","nilai":"178"},{"week":"22","nilai":"72"},{"week":"21","nilai":"164"},{"week":"21","nilai":"42"},{"week":"20","nilai":"193"},{"week":"20","nilai":"50"},{"week":"19","nilai":"186"},{"week":"19","nilai":"56"}]');
print_r($values);
$result = array_reduce($values, function ($carry, $item) {
$carry[$item->week] = (object) [
'week' => $item->week,
'nilai' => ($carry[$item->week]->nilai ?? 0) + $item->nilai,
];
return $carry;
}, []);
print "RESULT ... \n";
print_r($result);
Running on Repl.it at https://repl.it/repls/NauticalDamagedBytecode
This solution gives you an array that is keyed by the week number so that you can directly access them without further looping inside the array to retrieve them.
If you do not want that and if you want the array to me indexed like 0, 1, 2, 3, ... them do $result = array_values(array_reduce( ... )) or $result = array_values($result)

PHP strange str_split array output

Ok, im having troubles figuring out why my str_split is giving strange array output, this is the code:
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, 20, 23, "string3"),
4 => array(44, 55, 66, 77)
);
$newArray = array();
$keys = array_keys($test);
for($i=0; $i < count($test); $i++){
foreach($test[$keys[$i]] as $key => $value){
}
$output = str_split($key);
echo "<pre>";
print_r($output);
echo "</pre>";
Array output is:
Array
(
[0] => 3
)
Array
(
[0] => 3
)
Array
(
[0] => 3
)
Array
(
[0] => 4
)
Array
(
[0] => 3
)
And im expecting output like this:
Array ([0] => 3
[1] => 3
[2] => 3
[3] => 4
[4] => 3
)
Im wondering why is this happening? Thank you.
To achieve the output given, you would just do:
<?php
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, 20, 23, "string3"),
4 => array(44, 55, 66, 77)
);
foreach ($test as $row) {
$output[] = count($row)-1; // non-associative, so the last key is
} // just the length of the array minus 1
print_r($output);
?>
as the sub-arrays are not associative.
If they are, replace the line inside the loop with:
$keys = array_keys($row); // get the keys of the row
$output[] = $keys[count($keys)-1]; // and access the last of them
with your code the solution is, but it is not an efficient way of doing it.
<?php
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, 20, 23, "string3"),
4 => array(44, 55, 66, 77)
);
$newArray = array();
$keys = array_keys($test);
for($i=0; $i < count($test); $i++){
foreach($test[$i] as $key => $value){
$output[$i] = str_split($key)[0];
}
echo "<pre>";
//print_r($output);
echo "</pre>";
}
var_dump($output);
output
array (size=5)
0 => string '3' (length=1)
1 => string '3' (length=1)
2 => string '3' (length=1)
3 => string '4' (length=1)
4 => string '3' (length=1)
But by changing it to this will work, for arrays when the string position is not constant .
<?php
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, "string3", 20, 23),
4 => array(44, 55, 66, 77)
);
$newArray = array();
$keys = array_keys($test);
for($i=0; $i < count($test); $i++){
foreach($test[$i] as $key => $value){
if(is_string($value)){
unset($test[$i][$key]);
}
$output[$i] = count($test[$i]);
}
echo "<pre>";
//print_r($output);
echo "</pre>";
}
var_dump($output);
output
array (size=5)
0 => int 3
1 => int 3
2 => int 3
3 => int 4
4 => int 4

need soting multi dimensional array based on another array displaying order

I need sorting array based another array sort value.
Actual array : array(name=>'JK',age=>'20',place=>'India',year=>array(marks1=>array(sub1=>50,sub3=>70,sub7=>65,sub5=>75,sub4=>35), marks2=>array(sub8=>50,sub10=>70,sub12=>75,sub9=>35,sub11=>65))
sorting order array : array(name=>1,year=>2,age=>3,place=>4,sub1=>5,sub3=>6,sub4=>7,sub5=>8,sub7=>9,sub8=>10,sub9=>11,sub10=>12,sub11=>13,sub12=>14)
expected result array:
array(
name=>'JK',
year=>array(
marks1=>array(
sub1=>50,
sub3=>70,
sub4=>35,
sub5=>75
sub7=>65
),
marks2=>array(
sub8=>50,
sub9=>35,
sub10=>70,
sub11=>65,
sub12=>75
),
age=>'20',
place=>'India'
)
I hope this will help :)
$array1 = array(name=>'JK',age=>'20',place=>'India',year=>array(marks1=>array(sub1=>50,sub3=>70,sub7=>65,sub5=>75,sub4=>35), marks2=>array(sub8=>50,sub10=>70,sub12=>75,sub9=>35,sub11=>65));
$array2 = array(name=>1,year=>2,age=>3,place=>4,sub1=>5,sub3=>6,sub4=>7,sub5=>8,sub7=>9,sub8=>10,sub9=>11,sub10=>12,sub11=>13,sub12=>14);
//final array
$final_array = array();
//for each value in sorting array
foreach ($array2 as $key => $value)
{
//store result in final array
$final_array[$value] = $array1[$key];
}
//display array for check result
var_dump($final_array);
I am not exactly sure what is being asked. However, I will take a shot. I think the function you are looking for is uksort.
<?php
$array1 = array(name=>'JK',age=>'20',place=>'India',year=>array(marks1=>array(sub1=>50,sub3=>70,sub7=>65,sub5=>75,sub4=>35), marks2=>array(sub8=>50,sub10=>70,sub12=>75,sub9=>35,sub11=>65)));
function sorter($a,$b)
{
$array2 = array(name=>1,year=>2,age=>3,place=>4,sub1=>5,sub3=>6,sub4=>7,sub5=>8,sub7=>9,sub8=>10,sub9=>11,sub10=>12,sub11=>13,sub12=>14);
return $array2[$a] > $array2[$b];
}
uksort($array1, "sorter");
var_dump($array1);
?>
Here is an example of it running on codepad. You will probably have to work out a bit more since the subs are not sorted. But, possibly is_array can help you out.
$arr1 = array(
'name' => 'JK',
'age' => 20,
'place' => 'India',
'year' =>
array(
'marks1' =>
array('sub1' => 50,
'sub3' => 70,
'sub7' => 65,
'sub5' => 75,
'sub4' => 35),
'marks2' =>
array('sub8' => 50,
'sub10' => 70,
'sub12' => 75,
'sub9' => 35,
'sub11' => 65)));
$arr2 = array('name' => 1, 'year' => 2, 'age' => 3, 'place' => 4, 'sub1' => 5, 'sub3' => 6, 'sub4' => 7, 'sub5' => 8, 'sub7' => 9, 'sub8' => 10, 'sub9' => 11, 'sub10' => 12, 'sub11' => 13, 'sub12' => 14);
foreach ($arr1['year'] as $key => &$value){
uksort($value, function ($a, $b) use($arr2){
return $arr2[$a] - $arr2[$b];
});
}
uksort($arr1, function ($a, $b) use($arr2){
return $arr2[$a] - $arr2[$b];
});
print_r($arr1);
Output:
Array
(
[name] => JK
[year] => Array
(
[marks1] => Array
(
[sub1] => 50
[sub3] => 70
[sub4] => 35
[sub5] => 75
[sub7] => 65
)
[marks2] => Array
(
[sub8] => 50
[sub9] => 35
[sub10] => 70
[sub11] => 65
[sub12] => 75
)
)
[age] => 20
[place] => India
)

sort array on clothing sizes (multidimensional array)

My array looks like this:
Array
(
[0] => Array
(
[id] => 613
[kleur] => royalblauw/wit
[maat] => maat XL
[voorraad] => 100
[sort] => 0
[prijs] => 4.1320
)
[1] => Array
(
[id] => 614
[kleur] => royalblauw/wit
[maat] => maat XXL
[voorraad] => 100
[sort] => 1
[prijs] => 4.1320
)
[2] => Array
(
[id] => 620
[kleur] => zwart/wit
[maat] => maat XL
[voorraad] => 100
[sort] => 2
[prijs] => 4.1320
)
etc.etc.
What I want is to sort the array by 'maat' (size). As you can see there are multiple entries with same 'maat'.
I've been trying for hours now, but still not a good result. Ofcourse I've been looking at Stackoverflow, too. This is what I have until now.
Functions:
function cmp($a, $b)
{
$sizes = array(
"116" => 0,
"128" => 1,
"140" => 2,
"152" => 3,
"164" => 4,
"XXS" => 5,
"XS" => 6,
"S" => 7,
"M" => 8,
"L" => 9,
"XL" => 10,
"XXL" => 11,
"XXXL" => 12,
"XXXXL" => 13,
"XXXXXL" => 14
);
$asize = $sizes[$a];
$bsize = $sizes[$b];
if ($asize == $bsize) {
return 0;
}
return ($asize > $bsize) ? 1 : -1;
}
function aasort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii]=$va[$key];
}
uasort($sorter, "cmp");
foreach ($sorter as $ii => $va) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
}
And calling the function aasort:
aasort($maatkleur_array,"maat");
Please can you help me. I hope it's clear what I want to achieve.
You want to sort an array of arrays. The parent array don't have a (named) key. uasort perserves the key wich you don't want in your case so use usort in stead:
error_reporting(E_ALL);
ini_set('display_errors','on');
function cmp($a, $b)
{
$sizes = array('s'=>0,'m'=>'1','l'=>2,'xl'=>3);
if ($sizes[$a['maat']] == $sizes[$b['maat']]) {
return 0;
}
return ($sizes[$a['maat']] < $sizes[$b['maat']]) ? -1 : 1;
}
$input = array(
array('id'=>1,'kleur'=>'blauw','maat'=>'xl'),
array('id'=>2,'kleur'=>'blauw','maat'=>'m'),
array('id'=>1,'kleur'=>'blauw','maat'=>'s'),
array('id'=>2,'kleur'=>'blauw','maat'=>'m'),
array('id'=>3,'kleur'=>'blauw','maat'=>'l')
);
usort($input, "cmp");
print_r($input);
I have changed your cmp function little to achieve what you excepting..
$sort = array();
// $arrayData is your main array
foreach($arrayData as $key => $value)
{
$sort[$key] = cmp(strtoupper(str_replace('maat ', '', $value['maat'])));
}
array_multisort($sort, SORT_ASC, $arrayData);
function cmp($a)
{
$sizes = array(
"116" => 0,
"128" => 1,
"140" => 2,
"152" => 3,
"164" => 4,
"XXS" => 5,
"XS" => 6,
"S" => 7,
"M" => 8,
"L" => 9,
"XL" => 10,
"XXL" => 11,
"XXXL" => 12,
"XXXXL" => 13,
"XXXXXL" => 14
);
return $sizes[$a];
}
sort is based cmp function return value.
$arrayData will have sorted array based on maat size.
EDIT:
Use this callback instead. This will do the trick:
<?php
function usort_callback($a, $b) {
$sizes = array(
"116" => 0,
"128" => 1,
"140" => 2,
"152" => 3,
"164" => 4,
"XXS" => 5,
"XS" => 6,
"S" => 7,
"M" => 8,
"L" => 9,
"XL" => 10,
"XXL" => 11,
"XXXL" => 12,
"XXXXL" => 13,
"XXXXXL" => 14
);
$value1 = $sizes[trim(str_replace('maat', '', $a['maat']))];
$value2 = $sizes[trim(str_replace('maat', '', $b['maat']))];
return ($value1 < $value2) ? -1 : 1;
}
?>
ORIGINAL POST:
Try it with usort():
<?php
function usort_callback($a, $b) {
return strcmp($a['maat'], $b['maat']);
}
usort($array, "usort_callback");
?>
Now your array should be sorted by the key "maat"

PHP - Reorder array to match the order of another array

I have 1 array that has the right values that I need but it is out of order. I then have another array with the same keys and it is in the right order but the values are not what I need.
Here is my first array with the correct values but is out of order:
Array
(
[countTotal] => 7268
[zip] =>
[yearName] =>
[countZipRadius] =>
[Acura] => 1334
[Cadillac] => 511
[Ford] => 5423
)
Here is my second array with the right order but the wrong values:
Array
(
[countZipRadius] => 0
[zip] => 1
[yearName] => 2
[Acura] => 3
[Cadillac] => 4
[Ford] => 5
[countTotal] => 6
)
I am trying to figure out a way to create a new array with the right values from array 1 but that is in the order of array 2.
I have been playing with it for awhile and cannot seem to get it.
Any help would be great.
Thanks!
$c = array();
foreach (array_keys($b) as $k) {
$c[k] = $a[k];
}
You could use php's array_multisort function:
$original = array(
'countTotal' => 7268,
'zip' => '',
'yearName' => '',
'countZipRadius' => '',
'Acura' => 1334,
'Cadillac' => 511,
'Ford' => 5423,
);
$right = array(
'countZipRadius' => 0,
'zip' => 1,
'yearName' => 2,
'Acura' => 3,
'Cadilac' => 4,
'Ford' => 5,
'countTotal' => 6
);
//make sure both arrays are in the same order
ksort($original);
ksort($right);
array_multisort($right, $original);
print_r($original);
When you give it two arrays with the same number of elements it sorts both arrays, based on the order of the first array - in this case the 0, 1, 2, 3, etc. values in $right
Create a New Array (Array C)
Use a FOR loop to go through Array B
For each value in Array B, get the value with the same key from Array A and set Array C append those values to Array C. This will put them in the correct order in C.
Using scones' method:
$original = array(
'countTotal' => 7268,
'zip' => '',
'yearName' => '',
'countZipRadius' => '',
'Acura' => 1334,
'Cadillac' => 511,
'Ford' => 5423,
);
$right = array(
'countZipRadius' => 0,
'zip' => 1,
'yearName' => 2,
'Acura' => 3,
'Cadilac' => 4,
'Ford' => 5,
'countTotal' => 6
);
foreach ($right as $key => $value) {
$new[$key] = $original[$key];
}
print_r($new);
$array = array('a' => 100, 'b' => '5');
$newArray = array_combine(array_keys($array), range(0, count($array) - 1));
var_dump($newArray);

Categories