Sort array of months with laravel collection - php

My array is
$array = [
1 => 0
2 => 0
3 => 0
4 => 0
5 => 0
6 => 0
7 => 2
8 => 0
9 => 0
10 => 1
11 => 0
12 => 1
];
As a result i want it to be
$array = [
10 => 1
11 => 0
12 => 1
1 => 0
2 => 0
3 => 0
4 => 0
5 => 0
6 => 0
7 => 2
8 => 0
9 => 0
];
And my logic for now is
$sorted = collect($array)
->sortBy(function ($count, $month) {
return $month <= 9;
});
But the result is not what I expected :(
Basically i want last index to be current month and so on back.
Please help me!

You can do it like this:
$sorted = collect($array)->sortBy(function ($count, $month) {
$currentMonth = (int) \Carbon\Carbon::now()->month;
return ($month + (12 - $currentMonth - 1)) % 12;
});

You can function form php that
krsort();
krsort can sort associative arrays in descending order, according to the key. So
ksort($array);

Related

how to compare 2 array and compare difference of same id in php?

this questin is asked many times but every one using same array but in my case i have 2 arrays
consider i have 2 arrays
array1:3 [
10 => 900.0
20 => 450.0
30 => 600.0
]
array2:3 [
30 => 200.0
10 => 500.0
20 => 600.0
]
output should be
[900.0 - 500 = 400 // according to same id 10 = 10
450.0 - 600 = -150 // 20 = 20
600.0 - 200 = 400 // 30 = 30
]
in this array consider 10,20,30 are ids and next is value i want output where compare ever id and get difference example if (id1 = id2 ){ id1 => value - id2 => value }
i need help in that code which i already tried
$getsellerreport = SellerSellsReport::where('seller_id' , $seller_id);
$getunitdiff = $getsellerreport->pluck('unit')->toArray();// [0 => 75 1 => 500 => 100]
$getamountdiff = $getsellerreport->pluck('amount')->toArray(); // [0 => 11000 => 40 2 => 900]
$getproductdiff = $getsellerreport->pluck('product_id')->toArray(); // [0 => 39 1 => 242 => 23]
foreach($product_report as $preport){
$unit[] = $preport['unit'];// [0 => 75 1 => 25 2 => 100]
$amount[] = $preport['amount'];// [0 => 900 1 => 450 2 => 600]
$product_id[] = $preport['product_id'];// [0 => 23 1 => 242 => 39]
} // here we get array two values
above code get values with starting 0 key value and on below for() loop we can use product_id to compare both product id and get unit and amount but i dont know how i can do that can someone help me?
for ($i = 0 ; $i < sizeof($amount) ; $i++){
$unitdiff[] = $getunitdiff[$i] - $unit[$i];
$amountdiff[] = $getamountdiff[$i] - $amount[$i];
}
You could collect the arrays and use map, here is a sample to get you started:
$a = [
10 => 900.0,
20 => 450.0,
30 => 600.0,
];
$b = [
30 => 200.0,
10 => 500.0,
20 => 600.0,
];
$x = collect($a)->map(function($aItem, $index) use ($b) {
return $aItem - $b[$index];
});
dd($x); // yields [ 10 => 400.0, 20 => -150.0, 30 => 400.0 ]

Total for columns in a table

I want to calculate the totals for a series of columns in a table, how do I go about doing this?
Here is a sample of the data I want to sum:
array:1 [
"traders" => array:6 [
"Jim Mayor__targeted_target" => array:2 [
"amounts" => array:13 [
0 => 5
1 => 5
2 => 0
3 => 0
4 => 0
5 => 0
6 => 0
7 => 0
8 => 0
9 => 0
10 => 0
11 => 0
]
"row_name" => "Targeted target"
]
"Jim Mayor__actual_targeted" => array:2 [
"amounts" => array:13 [
0 => 0
1 => 1
2 => 0
3 => 0
4 => 0
5 => 0
6 => 1
7 => 1
8 => 0
9 => 0
10 => 0
11 => 0
]
"row_name" => "Actual targeted"
]
"Bob Martinez__targeted_target" => array:2 [
"amounts" => array:13 [
0 => 1
1 => 0
2 => 0
3 => 0
4 => 0
5 => 0
6 => 0
7 => 0
8 => 0
9 => 0
10 => 0
11 => 0
]
"row_name" => "Targeted target"
]
"Bob Martinez__actual_targeted" => array:2 [
"amounts" => array:13 [
0 => 19
1 => 45
2 => 20
3 => 26
4 => 21
5 => 10
6 => 12
7 => 20
8 => 11
9 => 2
10 => 0
11 => 0
]
"row_name" => "Actual targeted"
]
...
I want to sum together each index, e.g. for Jim Mayor__targeted_target, index 0 added to index 0 of Bob Martinez__targeted_target (this gives the total for January). It needs to work with an unlimited number of traders.
The function that generates the data:
protected function addRow($func, $params, $data, $year, $traderName, $rowName, $type, $image = null, $format = null, $underline = false)
{
$date = Carbon::createFromDate($year, 4, 1);
$total = 0;
$traderName = $traderName . '__' . str_replace(' ', '_', strtolower($rowName));
for ($i = 1; $i < 13; $i++) {
$params[1] = $date->year;
$params[2] = $date->month;
$result = call_user_func_array($func, $params);
$data['traders'][$traderName]['amounts'][] = $result ? $result : 0;
$total += $result;
$date->addMonth();
}
$data['traders'][$traderName]['amounts'][] = $total;
$data['traders'][$traderName]['row_name'] = $rowName;
return $data;
}
Just go over your data and save results in an additional array:
$results = array();
foreach ($traders as $trader) {
foreach ($trader['amounts'] as $i => $amount) {
if (!isset($results[$i])) {
$results[$i] = 0;
}
$results[$i] += $amount;
}
}
The result array will contains the sums of all traders.
Not tested but should work.
Do something like this:
function sumRowsByMonth($traders)
{
$sums = array_fill(0, 12, 0);
foreach($traders as $trader) {
foreach($trader['amounts'] as $monthId => $amount) {
$sums[$monthId] += $amount;
}
}
return $sums;
}
I tested with this:
$arr = array(
'traders' => array(
'Jim Mayor__targeted_target' => array(
'amounts' => array(
0 => 5,
1 => 5,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 0,
10 => 0,
11 => 0,
)
),
'Bob Martinez__targeted_target' => array(
'amounts' => array(
0 => 19,
1 => 45,
2 => 20,
3 => 26,
4 => 21,
5 => 10,
6 => 12,
7 => 20,
8 => 11,
9 => 2,
10 => 0,
11 => 0,
)
),
),
);
var_dump(sumRowsByMonth($arr['traders']));
Use array_sum() function.
array_sum() returns the sum of values in an array
Also, you said you want to count targeted target and actual targeted separately.
$actual = [];
$targeted = [];
foreach ($traders as $trader) {
$sum = array_sum($trader['anmounts']);
$trader['row_name'] === 'Actual targeted') ? $actual += $sum : $target += $sum;
}
Maybe you'll need to modify this a little bit to tune behavior, but I guess I got the idea.
#imperium2335:
The main problem I keep getting that it is summing all rows, including actual_targeted. actual_targeted needs to be grouped and summed separately to targeted_target.
Then do this:
function sumRowsByMonth($traders)
{
$sums = array();
foreach($traders as $traderName => $trader) {
$type = strstr($traderName, '__');
if( empty($sums[$type]) ) {
$sums[$type] = array_fill(0, 12, 0);
}
foreach($trader['amounts'] as $monthId => $amount) {
$sums[$type][$monthId] += $amount;
}
}
return $sums;
}
Read this:
http://php.net/manual/en/function.strstr.php

How to generate an array using a default values array and a new values array?

I have an array $d_visitors = array_count_values($d_visitors);
array:7 [▼
2 => 4
5 => 1
8 => 2
3 => 1
1 => 2
9 => 3
0 => 2
]
I'm trying to loop through that array 24 times, and check if the key matches, and store its value.
$dv = [];
for ($i = 0; $i < 24; $i++){
foreach ($d_visitors as $k =>$v) {
if($i == $k ){
$dv[$i] = $v;
}else{
$dv[$i] = 0;
}
}
}
I'm trying to print out something like this:
array:24 [▼
0 => 2
1 => 2
2 => 4
3 => 1
4 => 0
5 => 1
6 => 0
7 => 0
8 => 2
9 => 3
10 => 0
11 => 0
12 => 0
13 => 0
14 => 0
15 => 0
16 => 0
17 => 0
18 => 0
19 => 0
20 => 0
21 => 0
22 => 0
23 => 0
]
But I kept getting this:
array:24 [▼
0 => 2
1 => 0
2 => 0
3 => 0
4 => 0
5 => 0
6 => 0
7 => 0
8 => 0
9 => 0
10 => 0
11 => 0
12 => 0
13 => 0
14 => 0
15 => 0
16 => 0
17 => 0
18 => 0
19 => 0
20 => 0
21 => 0
22 => 0
23 => 0
]
Try this way:
$dv = [];
for ($i = 0; $i < 24; $i++){
$dv[$i] = 0;
if (isset($d_visitors[$i])) {
$dv[$i] = $d_visitors[$i];
}
}
More simplified is:
$dv = [];
for ($i = 0; $i < 24; $i++){
$dv[$i] = isset($d_visitors[$i])? $d_visitors[$i] : 0;
}
The problem in your code is in line $dv[$i] = 0; as it sets to zero $dv[$i] which earlier has been set.
You need to use one flag variable. Your code is also correct.
Try like this:
$dv = [];
$flag = 0;
for ($i = 0; $i < 24; $i++){
$flag = 0;
foreach ($d_visitors as $k =>$v) {
if($i == $k ){
$dv[$i] = $v;
$flag = 1;
}
}
if($flag == 0){
$dv[$i] = 0;
}
}
Another way of asking your process is:
How can I:
merge a default array with another array based on keys
and ksort() the result array?
While you can achieve your desired result using a foreach() loop and a condition statement on each iteration, I can show you a more concise, simple approach:
This is your new array of data: $array=[2=>4,5=>1,8=>2,3=>1,1=>2,9=>3,0=>2];
There are two ways to set up your default data array:
$defaults=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; // 24 elements with 0 value
or more elegantly:
$defaults=array_fill(0,24,0);
Then you only need to call array_replace() to overwrite the default values with the new values. This will keep the keys in ASC order.
var_export(array_replace($defaults,$array));
You can even nest the function calls and avoid adding variable names to the global scope like this:
$d_visitors=array_replace(array_fill(0,24,0),array_count_values($d_visitors)));
Done -- merged and ksorted.
To show some other ways that programmers might try to combine the two arrays (fruitlessly or illogically), here is a demonstration.

How to sort string index of php array

I am interested to sort php array index key in ascending order,
I have this array
(
[462 1 5.300] => 1
[462 9 4.900] => 1
[462 9 4.300] => 1
[462 2 4.800] => 1
[462 6 4.700] => 1
[462 7 4.900] => 1
[462 7 4.700] => 1
[462 8 4.500] => 1
[462 3 4.500] => 1
[462 4 4.700] => 1
[462 3 4.700] => 1
[462 5 4.500] => 1
)
I expect output to be like this after sort
(
[462 1 5.300] => 1
[462 2 4.800] => 1
[462 3 4.500] => 1
[462 3 4.700] => 1
[462 4 4.700] => 1
[462 5 4.500] => 1
[462 6 4.700] => 1
[462 7 4.700] => 1
[462 7 4.900] => 1
[462 8 4.500] => 1
[462 9 4.300] => 1
[462 9 4.900] => 1
)
I want to sort first 3 index which is used as string is it possible ? I have 3 more column in array but I am showing only 3 columns here..
A normal ksort() can do the trick, but if the sorting is to be performed in multiple orders (different orders for different parameter values), this wouldn't work.
You can achieve this with array_multisort(). First you create three (or more, depending on the number of parameters you have) arrays - each containing the parameter values. Then simply pass it to array_multisort() with the corresponding sort flag:
$param1 = $param2 = $param3 = array();
foreach ($data as $key => $value) {
$parts = explode(' ', $key);
$param1[] = $parts[0];
$param2[] = $parts[1];
$param3[] = $parts[2];
}
array_multisort($data, $param1, SORT_ASC, $param2, SORT_ASC, $param3, SORT_ASC);
If you want the sorting to be performed in descending order, then you can use SORT_DESC instead. See the documentation for a list of available sort flags.
Demo
The function usort() would be the answer, but you need to sort by key, not by value. So you'd have to use uksort().
Tiny help for you (not tested):
<?php
function cmp($a, $b)
{
$aParts = explode(' ',$a);
$bParts = explode(' ',$b);
if($aParts[0] !== $bParts[0]) {
return ($aParts[0] >= $bParts[0]) ? -1 : 1;
}
if( (int) $aParts[1] !== (int) $bParts[1]) { // compare second parts as integer
return ($aParts[1] >= $bParts[1]) ? -1 : 1;
}
if( (float) $aParts[2] !== (float) $bParts[2]) {
return ($aParts[2] >= $bParts[2]) ? -1 : 1;
}
return 0;
}
$a = array(
[462 1 5.300] => 1
[462 9 4.900] => 1
[462 9 4.300] => 1
[462 2 4.800] => 1
[462 6 4.700] => 1
[462 7 4.900] => 1
[462 7 4.700] => 1
[462 8 4.500] => 1
[462 3 4.500] => 1
[462 4 4.700] => 1
[462 3 4.700] => 1
[462 5 4.500] => 1
);
uksort($a, "cmp");
foreach ($a as $key => $value) {
echo "$key: $value\n";
}
In order to get the output you are showing, you can use the ksort() function -http://www.php.net/manual/fr/function.ksort.php.
<?php
$test = array(
"462 1 5.300" => 1,
"462 9 4.900" => 1,
"462 9 4.300" => 1,
"462 2 4.800" => 1,
"462 6 4.700" => 1,
"462 7 4.900" => 1,
"462 7 4.700" => 1,
"462 8 4.500" => 1,
"462 3 4.500" => 1,
"462 4 4.700" => 1,
"462 3 4.700" => 1,
"462 5 4.500" => 1
);
print_r($test);
ksort($test);
print_r($test);
?>

Converting a One-Dimensional Array into a Nested Array Using Relationship Keys

Say I have an array with keys representing id and values representing parent:
4 => 0
2 => 0
5 => 2
6 => 5
8 => 0
9 => 0
10 => 8
12 => 0
13 => 0
14 => 0
18 => 7
19 => 18
20 => 19
21 => 20
22 => 21
23 => 22
24 => 23
28 => 20
7 => 5
You could also read this as an object:
{
id : 4,
parent : 0
} // etc...
The multidimensional array I'd want to achieve from this would be:
4 => 0
2 => 5
=> 6
=> 7
=> 18
=> 19
=> 20
=> 21
=> 22
=> 23
=> 24
=> 28
8 => 10
9 => 0
12 => 0
13 => 0
14 => 0
How would I go about doing this?
If you write a little helper function to rework your data to a structure similar to:
$input = array(
array('id' => '4', 'parent' => '0'),
// ...
);
which could be achieved with something like:
$data = array_map(function ($entry) {
list($id, $parent) = array_map('trim', explode('=>', $entry));
return array(
'id' => $id,
'parent' => $parent
);
}, explode("\n", $data));
you could then use a function I used in a similar question:
function flatToNested($d, $r = 0, $p = 'parent', $k = 'id', $c = 'children') {
$m = array();
foreach ($d as $e) {
isset($m[$e[$p]]) ?: $m[$e[$p]] = array();
isset($m[$e[$k]]) ?: $m[$e[$k]] = array();
$m[$e[$p]][] = array_merge($e, array($c => &$m[$e[$k]]));
}
return $m[$r];
}
to produce a nested array with:
$nested = flatToNested($data);
demo: http://codepad.viper-7.com/HAZxaA

Categories