Reputation: 631
I want to group array values and find total (sum of array value-based of the group by value) and then sort array based on total. I want to group by users by fund type ("Private, VC, Others") and the sum of total fund ("last value")
I have set up a demo link here.
<?php
$data = [
[
'Jon',
'NO',
"",
"Private",
120
],
[
'Andew',
'NO',
"",
"VC",
150
],
[
'Walid',
'YES',
"",
"Other",
160
],
[
'Andew',
'YES',
"",
"VC",
150
],
[
'Andew',
'YES',
"",
"VC",
180
],
[
'Jon',
'NO',
"",
"Other",
150
],
[
'Andew',
'YES',
"",
"Other",
600
]
];
$arr = array();
foreach ($data as $key => $item) {
$arr[$item[0]][$key] = $item['4'];
}
var_dump($arr);
I want below output
Group by ("Private, VC, Others") so value format like [sum of the private, sum of VC, a sum of Others ]
Array
(
[Jon] => [120,110,0]
[Andew] => [0,480,600]
[Walid] => [0,0,160]
)
And then I want to sort array based on the total sum
Array
(
[Andew] => [0,480,600]
[Jon] => [120,110,0]
[Walid] => [0,0,160]
)
Anyone please suggest possible solution to fic this issue?
Thanks
Upvotes: 1
Views: 125
Reputation: 147146
If this is the result of a database query, this could almost certainly have been done more efficiently in that query. However, you can get the results you want in 3 stages:
$arr = array();
foreach ($data as $key => $item) {
$arr[$item[0]][$item[3]] = ($arr[$item[0]][$item[3]] ?? 0) + $item[4];
}
foreach (array_unique(array_column($data, 3)) as $type) {
foreach ($arr as &$person) {
if (!isset($person[$type])) $person[$type] = 0;
}
}
uasort($arr, function ($a, $b) {
return $b['Private'] + $b['Other'] + $b['VC'] - ($a['Private'] + $a['Other'] + $a['VC']);
});
Output (for your sample data):
Array
(
[Andew] => Array
(
[VC] => 480
[Other] => 600
[Private] => 0
)
[Jon] => Array
(
[Private] => 120
[Other] => 150
[VC] => 0
)
[Walid] => Array
(
[Other] => 160
[Private] => 0
[VC] => 0
)
)
Note I've left the keys of the inner array as associative as that seems more useful. If you would prefer numeric keys, you would need to sort each internal array so the keys were in the same order, and then take array_values
of each entry:
$key_rank = array('Private' => 0, 'VC' => 1, 'Other' => 2);
foreach ($arr as &$person) {
uksort($person, function ($a, $b) use ($key_rank) {
return $key_rank[$a] - $key_rank[$b];
});
$person = array_values($person);
}
Output:
Array
(
[Andew] => Array
(
[0] => 0
[1] => 480
[2] => 600
)
[Jon] => Array
(
[0] => 120
[1] => 0
[2] => 150
)
[Walid] => Array
(
[0] => 0
[1] => 0
[2] => 160
)
)
To get the results in the form of an array with the name and values together, replace the last piece of code with this:
$key_rank = array('Private' => 0, 'VC' => 1, 'Other' => 2);
$result = array();
foreach ($arr as $name => &$person) {
uksort($person, function ($a, $b) use ($key_rank) {
return $key_rank[$a] - $key_rank[$b];
});
$result[] = array_merge(array($name), array_values($person));
}
print_r($result);
Output:
Array
(
[0] => Array
(
[0] => Andew
[1] => 0
[2] => 480
[3] => 600
)
[1] => Array
(
[0] => Jon
[1] => 120
[2] => 0
[3] => 150
)
[2] => Array
(
[0] => Walid
[1] => 0
[2] => 0
[3] => 160
)
)
[Demo on 3v4l.org][3]
Upvotes: 1