I need to create a multidimensional array [duplicate] - php

This question already has answers here:
How to store values from foreach loop into an array?
(9 answers)
Closed 3 years ago.
I'm trying to create a multidimensional array in Laravel 5.8 but I can't seem to get it to work.
It's running on PHP 7.3 and Laravel 5.8.
Here's what I've already try:
foreach ($locations as $location) {
$email_data = array($address => array($location));
}
$arr = array($email_data[count($email_data)-1] => $address);
for ($i=count($email_data) - 2 ; $i>=0 ; $i--) {
$arr = array($email_data[$i] => $arr);
}
foreach ($ageMatches as $ageMatch) {
$age['Age'] = $ageMatch[1];
array_push($arr, $age);
}
Here's the data I'm using:
ELY FARM
THE ADDRESS
BW8010 2.55 UNIT 1
Logged 03 JUN 19 23:59
SUMMARY REPORT
----UNIT 1 PERCH 1-----
House 1, Pen 1
Age DAYS 7
Total 3997
Average GMS 64
Deviation GMS 14
Evenness % 29
C.V. % 21.9
Daily gain GMS 9
----UNIT 1 PERCH 2-----
House 1, Pen 2
Age DAYS 7
Total 3849
Average GMS 73
Deviation GMS 17
Evenness % 29
C.V. % 23.3
Daily gain GMS 9
So I want to to be like:
array(
"Ely Farm" => array(
"Unit 1 Perch 1" => array(
"Age" => 7,
"Total" => 3849,
),
"Unit 1 Perch 2" => array(
"Age" => 7,
)
),
"Next Location" => array(
array(
),
);
At the moment I have the following and I can't work where I'm going wrong (if I dump $location[1] it does come out with the location instead of hyphens but when I don't dump it comes out as below).
array:1 [▼
"Ely Farm" => array:1 [▼
0 => array:2 [▼
0 => "------------------------"
1 => "---------------"
]
]
]

In this block you are rewriting $email_data each iteration
foreach ($locations as $location) {
$email_data = array($address => array($location));
}
What you should do instead is
foreach ($locations as $location) {
$email_data[] = array($address => array($location));
}
This will continuously add the values instead of replacing them. You have the same issue below too with $arr

Related

Compare two arrays and if one month (key) is missing fill with 0

Hello I've got two arrays, one which is made with Carbon that takes the last 12 months from today (in Y-m format) and a Collection (which have an array of items that return every transaction of the last 12 months in the same Y-m format). What I want to do is fill in this items array if there's no transaction for example on the month 12, 9, 8 fill them with 0.
Here's the 2 arrays I need compared and fill missing Year-month with 0 (the last array is the balance which will be merged into the array for every month).
^ array:12 [▼
"2022-02" => 0
"2022-03" => 0
"2022-04" => 0
"2022-05" => 0
"2022-06" => 0
"2022-07" => 0
"2022-08" => 0
"2022-09" => 0
"2022-10" => 0
"2022-11" => 0
"2022-12" => 0
"2023-01" => 0
]
^ array:12 [▼
"2022-01" => 0
"2022-02" => 1
"2022-03" => 2
"2022-04" => 3
"2022-06" => 4
"2022-07" => 5
"2022-08" => 6
"2022-09" => 7
"2022-10" => 8
"2022-11" => 9
"2022-12" => 10
"2023-01" => 11
]
^ array:12 [▼
0 => 340
1 => 480
2 => 550
3 => 690
4 => 830
5 => 970
6 => 1110
7 => 1250
8 => 1460
9 => 1600
10 => 1670
11 => 1880
]
The code I used at the moment to find the balance per month (the latest balance of the month) but at the moment I dont print the missing months (it just skips them instead of filling with 0):
$period = CarbonPeriod::create(now()->subMonths(11), now())->month();
$dates = array();
$days = array();
foreach($period as $date) {
$dates[] = $date->format("Y-m");
$days[] = $date->lastOfMonth()->format("d-m-Y");
}
$userTransactions = auth()->user()->transactions;
$flipped = array_flip($dates);
$transactionsByMonth = $userTransactions->groupBy(function($d) {
$monthlyTransaction = Carbon::parse($d->created_at)->format('Y-m');
return $monthlyTransaction;
});
foreach($flipped as $key => $yearMonth){
$yearMonth = 0;
$flipped[$key] = $yearMonth;
}
dump($flipped);
foreach($transactionsByMonth as $transaction) {
if (sizeof($transaction) > 1){
$duplicatedTransactions = $transaction->groupBy(function($d) {
return Carbon::parse($d->created_at)->format('Y-m-d');
});
$lastDuplicatedTransactions = $duplicatedTransactions->last();
foreach($lastDuplicatedTransactions as $lastTransaction){
$transactionDates[] = $lastTransaction->created_at;
$transactionBalance[] = $lastTransaction->main_balance;
}
} else {
foreach($transaction as $notDuplicatedTransaction){
$transactionDates[] = $notDuplicatedTransaction->created_at;
$transactionBalance[] = $notDuplicatedTransaction->main_balance;
}
}
};
$transactionsPerMonth = [];
foreach($transactionDates as $date){
$date = Carbon::parse($date)->format('Y-m');
$transactionsPerMonth[] = $date;
}
$transactionsPerMonth = array_flip($transactionsPerMonth);
dump($transactionsPerMonth);
dump($transactionBalance);
At the moment I achieved printing the balance of the oldest day of the month on the last 12 months, what Im missing is comparing if of this 12 months if there's a month missing fill it with 0 instead of skipping it.
You can use array_key_exists() function to compare the two arrays and fill in missing months with 0.
Example:
$carbonMonths = ["2022-01", "2022-02", "2022-03", "2022-04", "2022-05", "2022-06", "2022-07", "2022-08", "2022-09", "2022-10", "2022-11", "2022-12"];
$transactions = [
["2022-01" => 200],
["2022-02" => 150],
["2022-03" => 100],
["2022-05" => 50]
];
foreach ($carbonMonths as $month) {
if (!array_key_exists($month, $transactions)) {
$transactions[$month] = 0;
}
}
In this example, the $carbonMonths array contains the last 12 months in Y-m format. The $transactions array contains transactions in the same format.
You can also use the array_merge() function to merge the two arrays and fill in any missing values with 0.
$merged = array_merge(array_fill_keys($carbonMonths, 0), $transactions);
Here $transactions should be an associative array with keys as month and value for this to work.
Both of the approach should give you the same result, you may use the one which you find easy to implement.
Improved the code to this:
$months = CarbonPeriod::create(now()->subMonths(11), now())->month();
$transactions = auth()->user()->transactions
->groupBy( fn($d) => Carbon::parse( $d->created_at )->format('Y-m'))->map->last();
$transactionsByMonth = collect($months)
->flatMap(function ($key) use ($transactions) {
$key = $key->format('Y-m');
return [$key => collect($transactions[$key]->main_balance ?? 0)];
});
$transactionsByMonth = $transactionsByMonth->toArray();
$transactionsByMonth = array_values($transactionsByMonth);
dump($transactionsByMonth);
But Im getting an array inside an array:
array:12 [▼
0 => array:1 [▼
0 => 480
]
1 => array:1 [▼
0 => 550
]
2 => array:1 [▼
0 => 690
]
3 => array:1 [▶]
4 => array:1 [▶]
5 => array:1 [▶]
6 => array:1 [▶]
7 => array:1 [▶]
8 => array:1 [▶]
9 => array:1 [▶]
10 => array:1 [▶]
11 => array:1 [▶]
]
So What I finally did to solve it was instead of returning the collect() for every $key I just returned the collect directly so I would stop getting an array inside an array.
Replaced this:
$transactionsByMonth = collect($months)
->flatMap(function ($key) use ($transactions) {
$key = $key->format('Y-m');
return [$key => collect($transactions[$key]->main_balance ?? 0)];
});
$transactionsByMonth = $transactionsByMonth->toArray();
$transactionsByMonth = array_values($transactionsByMonth);
dump($transactionsByMonth);
Into this:
$transactionsByMonth = collect($months)
->flatMap(function ($key) use ($transactions) {
$key = $key->format('Y-m');
return collect($transactions[$key]->main_balance ?? 0);
});
$transactionsByMonth = $transactionsByMonth->toArray();

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 ]

Calculate Age for each user from array of date using Laravel

i'm new to laravel i want to know if there are methode to calculate age from array so my content looks like this:
Collection {#231 ▼
#items: array:6 [▼
0 => "1928-11-18"
1 => "1938-06-15"
2 => "1939-03-30"
3 => "1941-11-08"
4 => "1940-04-29"
5 => "1987-06-24"
]
}
How to properly transform the array so that it contains only age like this
Collection {#231 ▼
#items: array:6 [▼
0 => 90
1 => 80
2 => 79
3 => 77
4 => 87
5 => 31
]
}
You can also use map method on collection
$collection = collect([0 => "1928-11-18",
1 => "1938-06-15",
2 => "1939-03-30",
3 => "1941-11-08",
4 => "1940-04-29",
5 => "1987-06-24"]);
$age = $collection->map(function ($item, $key) {
return Carbon::parse($item)->diff(Carbon::now())->format('%y');
});
return $age->all();
This will give you,
[
"89",
"79",
"79",
"76",
"78",
"30"
]
You can iterate trough a Collection with foreach() then convert to Age using Carbon ->age:
foreach ($collection as $key => $value) {
$collection[$key] = Carbon::parse($collection[$key])->age;
}
This will give you a Collection as what you do is editing the Collection, instead of creating a new array.
Use Carbon's ->age or diffInYears and collection transform (or map):
$dates->transform(function ($date) {
return \Carbon\Carbon::parse($date)->age;
});
Note: someone born on 1928-11-18 is 89 years old, not 90.

How to display array of column names between specific index value

I have the following array of column names, I want to only display the day column names, so 7 - 13
array:20 [▼
0 => "id"
1 => "customer_id"
2 => "enrolment_id"
3 => "course_id"
4 => "delivery_mode"
5 => "course_cost"
6 => "location"
7 => "Monday"
8 => "Tuesday"
9 => "Wednesday"
10 => "Thursday"
11 => "Friday"
12 => "Saturday"
13 => "Sunday"
14 => "start_time"
15 => "end_time"
16 => "start_date"
17 => "sale_type"
18 => "created_at"
19 => "updated_at"
]
Array is created in controller with:
$columns = Schema::getColumnListing('orders');
I'm using the following to display the column names as labels for my checkboxes in a blade template view but it shows all column names and not just the days:
#foreach($columns as $column)
{{ Form::checkbox($column, 0, null, ['id' => $column, 'class' => 'is-
checkradio is-white']) }}
{{ Form::label($column, $column) }}
#endforeach
Thanks Jonas
This worked for the question
$days = array_slice($columns, 7, 7);
You can use the array_where from laravel helpers (https://laravel.com/docs/5.4/helpers#method-array-where) to do this job, like this:
$columns = array_where($columns, function ($value, $key) {
return ($value >= 7 && $columns <= 13);
});

Fill multidimensional array from other array

I have a multidimensional array $elements where I need to fill it with values from the array $ratings. The array $ratings is built so the first value will fit into the first slot in elements, the next in the second and so on.
$elements
4 => array:3 [▼
2 => 0
3 => 0
4 => 0
]
5 => array:3 [▼
2 => 0
3 => 0
4 => 0
]
7 => array:3 [▼
2 => 0
3 => 0
4 => 0
]
I now need to fill $elements with 9 specific values from
$ratings
array:9 [▼
0 => 3
1 => 2
2 => 1
3 => 3
4 => 3
5 => 2
6 => 3
7 => 2
8 => 1
9 => 3
]
If I manage to loop through $elements, inserting values from $ratings one by one, I will have solved my problem.
So $elements[4][2] should have the value of 3, $elements[4][3] should have value of 2 etc.
Also you can manipulate these by array_fill using loop.
Try this:
<?php
$elements = [
4=>[2=>0, 3=>0, 4=>0],
5=>[2=>0, 3=>0, 4=>0],
7=>[2=>0, 3=>0, 4=>0],
];
$ratings = [ 0 => 3, 1 => 2, 2 => 1, 3 => 3, 4 => 3, 5 => 2, 6 => 3, 7 => 2, 8 => 1, 9 => 3 ];
$ratingsIndex = 0;
foreach(array_keys($elements) as $ElementsIndex) {
foreach(array_keys($elements[$ElementsIndex]) as $ElementsSubIndex) {
$elements[$ElementsIndex][$ElementsSubIndex] = $ratings[$ratingsIndex++];
}
}
echo "<pre>";
print_r($elements);
echo "</pre>";
?>

Categories