sort array on clothing sizes (multidimensional array) - php

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"

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)

How to subtract all column values in multi-dimensional array in Php?

How can I subtract all the columns values? My array is like
Array
(
[0] => Array
(
[id] => 1
[web_traffic] => 442
[form_users] => 131
[date] => 20181004
)
[1] => Array
(
[id] => 2
[web_traffic] => 102
[form_users] => 15
[date] => 20181003
)
[2] => Array
(
[id] => 3
[web_traffic] => 387
[form_users] => 97
[date] => 20181002
)
)
I need to subtract the each column(except date & id) and get the result based on date(Ascending order). For example 20181004 means 4th October 2018. My output should like the below
Array
(
[web_traffic] => -152
[form_users] => -49
)
My code took reference from How to sum all column values in multi-dimensional array?
foreach ($data as $value) {
unset($value[ 'id' ]);
$time = date('Ymd', strtotime($value[ 'date' ]));
if (in_array($time, $dates)) {
$value[ 'date' ] = $time;
foreach ($value as $key => $secondValue) {
if ( !isset($output[ $key ])) {
$output[ $key ] = 0;
}
$output[ $key ] -= $secondValue;
}
}
}
Use PHP array_reduce() and array_column() like this:
$initial_array = array(array('id' => 1,
'web_traffic' => 442,
'form_users' => 131,
'date' => 20181004),
array('id' => 2,
'web_traffic' => 102,
'form_users' => 15,
'date' => 20181003),
array('id' => 3,
'web_traffic' => 387,
'form_users' => 97,
'date' => 20181002));
function sum($carry, $item)
{
$carry -= $item;
return $carry;
}
$web_traffic = array_column($initial_array, "web_traffic");
$form_users = array_column($initial_array, "form_users");
$date = array_column($initial_array, "date");
array_multisort($date, SORT_ASC, $form_users, SORT_DESC, $initial_array);
$result_array = Array(
"web_traffic" => array_reduce(array_column($initial_array, "web_traffic"), "sum",2*$initial_array[0]['web_traffic']),
"form_users" => array_reduce(array_column($initial_array, "form_users"), "sum",2*$initial_array[0]['form_users'])
);
print_r($result_array);
I would first sort the array using usort() in example.
Sorting first, because that can be tricky to substract in 1 loop the oldest datas to the newers one.
Separating intentions provide a cleaner code, easier to maintain.
The dates don't need to be converted into a date. The string is well formatted and can be used as is in a comparison and a sort. "20170101" < "20180101", "20180101" < "20181001" and "20181002" < "20181004"
When done, I'll save the first values as initial values to be used in substract.
Then, loop the sorted array and substract the 'web_traffic' and 'form_users' to the initial values.
$datas = array(array('id' => 1,
'web_traffic' => 442,
'form_users' => 131,
'date' => 20181004),
array('id' => 2,
'web_traffic' => 102,
'form_users' => 15,
'date' => 20181003),
array('id' => 3,
'web_traffic' => 387,
'form_users' => 97,
'date' => 20181002));
//If needed, you can backup the original array, because usort() will modify it.
$backUpDatas = $datas;
//Sort
usort($datas, function ($arr1, $arr2)
{
if (isset($arr1['date']) && isset($arr2['date']))
{
if ($arr1['date'] == $arr2['date'])
return (0);
return (($arr1['id'] > $arr2['id']) ? (-1) : (1));
}
});
//Initial values
$finalValues['web_traffic'] = $datas[0]['web_traffic'];
$finalValues['form_users'] = $datas[0]['form_users'];
//Substract
foreach ($datas as $key => $value)
{
if ($key > 0)
{
if (isset($value['web_traffic']))
$finalValues['web_traffic'] -= $value['web_traffic'];
if (isset($value['form_users']))
$finalValues['form_users'] -= $value['form_users'];
}
}
var_dump($finalValues);
Output :
array (size=2)
'web_traffic' => int -157
'form_users' => int -49

php array sum key where value is same

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);
?>

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
)

Counting values within multidimensional arrays?

I have a large array where I basically need to count the number of uniques:
example array
The end result I am looking for something like
$result = array(
'A3D5' => array('P2' => 1, 'P3' => 1, 'P4' => 1, 'total' => 3),
'AE5S' => array('P4' => 1, 'total' => 1)
);
I've tried foreaching through but can't seem to figure out how to sort them into another key, something like $zone = "P{$array['zone']}"; $result[$zone][$prestige]++ or seems to kind of not work or just error.
$array = array(
"denizen" => array
(
"prestige" => 2,
"zone" => "A3D5",
"scope_frag" => 765
),
"생각" => array
(
"prestige" => 4,
"zone" => "A3D5",
"scope_frag" => 135
),
"Ryans" => array
(
"prestige" => 3,
"zone" => "A3D5",
"scope_frag" => 78
),
"지적인" => array
(
"prestige" => 2,
"zone" => "AE5S",
"scope_frag" => 481
)
);
foreach ($array as $group) {
$zones[$group["zone"]][] = $group["prestige"];
}
foreach ($zones as $name => $zone) {
$total = count($zone);
foreach ($zone as $prestige) {
$result[$name]["P".$prestige] += 1;
}
ksort($result[$name]);
$result[$name]["total"] = $total;
}
echo "<pre>";
print_r($result);
echo "</pre>";

Categories