Transform data with Laravel helpers - php

I have an array with the following format:
[
{
"stat_month": "01-2019",
"in_sum": 45443,
"out_sum": 42838,
"balance": 2605
},
{...}
]
But I want to transform this array, hopefully in one operation, to this:
[
"labels" => ["01-2019", "02-2019", "03-2019"],
"in_sum" => [45443, 60947, 56734],
"out_sum" => [42838, 42151, 75486],
"balance" => [2605, 18796, -18752]
]
Any ideas how to solve this in one operation with collection helper functions?

Look at mapToGroups in Laravel Collections:
https://laravel.com/docs/5.8/collections#method-maptogroups
or this solution:
$obj1 = new \stdClass;
$obj1->stat_month = "01-2019";
$obj1->in_sum = 45443;
$obj1->out_sum = 42838;
$obj1->balance = 2605;
$obj2 = new \stdClass;
$obj2->stat_month = "02-2019";
$obj2->in_sum = 55443;
$obj2->out_sum = 52838;
$obj2->balance = 3605;
$collection = collect([
$obj1,$obj2
]);
$aResult = [
'labels' => [],
'in_sum' => [],
'out_sum' => [],
'balance' => []
];
$collection->each(function ($item, $key) use (&$aResult) {
$aResult['labels'][] = $item->stat_month;
$aResult['in_sum'][] = $item->in_sum;
$aResult['out_sum'][] = $item->out_sum;
$aResult['balance'][] = $item->balance;
});
Result:
array:4 [▼
"labels" => array:2 [▼
0 => "01-2019"
1 => "02-2019"
]
"in_sum" => array:2 [▼
0 => 45443
1 => 55443
]
"out_sum" => array:2 [▼
0 => 42838
1 => 52838
]
"balance" => array:2 [▼
0 => 2605
1 => 3605
]
]

You can do this is php like this:
<?php
$array = '[
{
"stat_month": "01-2019",
"in_sum": 45443,
"out_sum": 42838,
"balance": 2605
},
{
"stat_month": "01-2019",
"in_sum": 45443,
"out_sum": 42838,
"balance": 2605
},
{
"stat_month": "01-2019",
"in_sum": 45443,
"out_sum": 42838,
"balance": 2605
}
]';
$array = json_decode($array, true);
$arrayResult = [
'stat_month' => array_column($array, 'stat_month'),
'in_sum' => array_column($array, 'in_sum'),
'out_sum' => array_column($array, 'out_sum'),
'balance' => array_column($array, 'balance')
];
echo "<pre>";
print_r($arrayResult);
?>

You can use simplified array_map() and receive desired output:
$i = 0;
$tmp = ['labels'=>[],'in_sum'=>[],'out_sum'=>[],'balance'=>[]];
array_map(function($obj) use (&$tmp, $i){
foreach($tmp as &$val){
$val[] = array_values(((array)$obj))[$i];
$i++;
}
},$ar);
Demo
Or just simple foreach loop:
$tmp = ['labels'=>[],'in_sum'=>[],'out_sum'=>[],'balance'=>[]];
foreach($ar as $obj) {
$i = 0;
foreach($tmp as &$val){
$val[] = array_values(((array)$obj))[$i];
$i++;
}
}
Demo2
You can replace and re-write this code with Laravel map() function. Try to use dynamic loops instead of predefined object's properties.

Related

Getting zero when extracting data from a PHP array in Laravel app

Am working on some set of PHP array. Am trying to loop through each of them and check
the array whose name is equal to Josw Acade. Am using a for loop but I get zero
after extracting the data. I want to store the data in an array.
Array
array:6 [
0 => array:4 [
"id" => 1
"name" => "Josw Acade"
"value" => "Unlimited"
"plan_type" => "Superior"
]
1 => array:4 [
"id" => 2
"name" => "Verbal"
"value" => "true"
"plan_type" => "Superior"
]
2 => array:4 [
"id" => 12
"name" => "Josw Acade"
"value" => "$1,500,00"
"plan_type" => "Classic"
]
3 => array:4 [
"id" => 13
"name" => "Leon"
"value" => "true"
"plan_type" => "Classic"
]
4 => array:4 [
"id" => 14
"name" => "One Time"
"value" => "true"
"plan_type" => "Classic"
]
5 => array:4 [
"id" => 15
"name" => "Deat"
"value" => "$25,000"
"plan_type" => "Classic"
]
6 => array:4 [
"id" => 23
"name" => "Josw Acade"
"value" => "$100,000"
"plan_type" => "Essential"
]
]
Logic
$Inst = [];
for($med = 0; $med < count($array); $med++){
if($med['name'] == "Josw Acade"){
$Inst = $med['value'];
}
}
dd($Inst);
Your variables is not corretly set in the for loop, you are setting $med = 0 and acessing $med as an array.
Use filter, that runs a condition on each element and returns the items that satisfy that condition.
array_filter($array, function ($item) {
return $item['name'] === 'Josw Acade';
});
In general you don't have to make old school arrays anymore, foreach does the same.
$results = [];
foreach($array as $item)
{
if ($item['name'] === 'Josw Acade') {
$results[] = $item['value'];
}
}
You can use array_filter with callback
$filtered = array_filter($array, function($v){ return $v['name'] == 'Josw Acade'})
print_r($filtered);
You are looping through array; so on each iteration to get values; you need to pass index value and you are missing that. You are using $med as index.
Here is code.
$Inst = [];
for($med = 0; $med < count($array); $med++){
if($array[$med]['name'] == "Josw Acade"){
$Inst[] = $array[$med]['value'];
}
}
there is many way to do this but according to me the best way to use array_filer()
array_filter($array, function ($item) {
return $item['name'] === 'Josw Acade';
});

Laravel get group of arrays

I have code below and result is like:
array:2 [▼
0 => array:1 [▼
"CPU" => "AMD a5"
]
1 => array:1 [▼
"CPU" => "AMD a9"
]
]
I want to group them in same array like
CPU => [
"0" => "AMD a5",
"1" => "AMD a9"
]
Code
$category = Category::where('slug', $slug)->where('status', '=', 'active')->first();
$products = $category->products;
foreach ($products as $product) {
foreach($product->attributes as $attribut){
$attributes[] = [$attribut->group->title => $attribut->title];
}
}
What should I change?
If you want a bit of a more scalable solution where you might have multiple attribute types, the following may help:
$attributes = [
[
'CPU' => 'AMD A5'
],
[
'CPU' => 'AMD A9'
],
[
'GFX' => 'AMD'
]
];
return collect($attributes)
->groupBy(function($item) {
return key($item);
})
->map(function($item) {
return array_flatten($item);
})
->toArray();
The output of the above will be:
array:2 [▼
"CPU" => array:2 [▼
0 => "AMD A5"
1 => "AMD A9"
]
"GFX" => array:1 [▼
0 => "AMD"
]
]
Here's an example you can play with.
if your $attribut->group->title is "CPU" and your $attribut->title is "AMD a5"
then you can use this
foreach ($products as $product) {
foreach($product->attributes as $attribut){
$attributes[$attribut->group->title][] = $attribut->title;
}
}
from #mozammil answer if you still wanna do using foreach
$attributes =
[
[
'CPU' => 'AMD A5'
],
[
'CPU' => 'AMD A9'
],
[
'GFX' => 'AMD'
]
];
$data = [];
foreach ($attributes as $titles){
foreach ($titles as $title=> $row){
$data[$title][] = $row;
}
}
You can try collection methods here is an example.
$keyed = $collection->map(function ($item,$key) {
return [[$key] => $item['CPU']];
});
For more information
https://laravel.com/docs/5.7/collections#method-map
Use array_column to get one column of an array.
$category = Category::where('slug', $slug)->where('status', '=', 'active')->first();
$products = $category->products;
$cpu = array_column($products, "CPU");
This will return an array as your expected result.
https://3v4l.org/UYPhK
This requires PHP 7 since in older versions array_column can't handle objects

How map array of array to single assoc array?

I have:
array:2 [
0 => array:1 [
"FNAME" => "nullable|string"
]
1 => array:1 [
"LNAME" => "nullable|string"
]
]
And I try to get:
array:1 [
"key" => "value"
]
I try map it, but has problem
<?php
$array = [
[
"FNAME" => "nullable|string",
],
[
"LNAME" => "nullable|string",
]
];
$newArray = [];
foreach ($array as $item) {
foreach ($item as $key => $value) {
$newArray[$key] = $value;
}
}
print_r($newArray);
Will output:
Array
(
[FNAME] => nullable|string
[LNAME] => nullable|string
)
Two simple ways:
print_r(array_merge(...$arr));
// if `...` is not available (php < 5.6), then:
print_r(call_user_func_array('array_merge', $arr))

How to parse a laravel collection

I have a laravel collection on output, I want to parse it ->toArray()
Collection {#335
#items: array:2 [
"0f39b1e0-a507-11e7-9d6e-33e84951047e" => array:2 [
"total_amount" => 25000
"debt_type" => array:2 [
0 => "car_loan"
1 => "car_loan"
]
]
"0f218520-a507-11e7-b0ba-8554a4ad039b" => array:2 [
"total_amount" => 15000
"debt_type" => array:1 [
0 => "house_loan"
]
]
]
}
is there any way to parse it so I get the following output:
array:1[
0=>[
'debt_id'=>'0f39b1e0-a507-11e7-9d6e-33e84951047e',
'debt_type'=>'car_loan',
'total_amount'=>25000
],
1=>[
'debt_id'=>'0f218520-a507-11e7-b0ba-8554a4ad039b',
'debt_type'=>'house_loan',
'total_amount'=>15000
]
]
what I have tried it works but not sure if its a good way to go around it:
$appDebts = $appDebts->groupBy('debt_type_id')->map(function ($item) {
return [
'total_amount' => $item->sum('amount'),
'debt_type' => $item->map(function ($item) {
return $item->debt_type->slug;
})->toArray(),
];
})->toArray();
if you dd $appDebts you get the collection that I have added on top of the post
$carLoan = [];
$studentLoan = [];
$houseLoan = [];
$cardLoan = [];
foreach ($appDebts as $debt) {
if ($debt['debt_type'][0] === 'car_loan') {
$carLoan['TotalAmount'] = $debt['total_amount'];
$carLoan['LoanType'] = $debt['debt_type'][0];
}
if ($debt['debt_type'][0] === 'house_loan') {
$houseLoan['TotalAmount'] = $debt['total_amount'];
$houseLoan['LoanType'] = $debt['debt_type'][0];
}
if ($debt['debt_type'][0] === 'student_loan') {
$studentLoan['TotalAmount'] = $debt['total_amount'];
$studentLoan['LoanType'] = $debt['debt_type'][0];
}
if ($debt['debt_type'][0] === 'credit_card_loan') {
$cardLoan['TotalAmount'] = $debt['total_amount'];
$cardLoan['LoanType'] = $debt['debt_type'][0];
}
}
Based on the array you shared:
$parsed = $collection->map(function ($item, $id) {
return [
'debt_id' => $id,
'debt_type' => collect($item['debt_type'])->first(),
'total_amount' => $item['total_amount']
];
})->values()->toArray();
With values you remove the key => value, you get the array without keys
Try with this mapping after the first one that you did :
$appDebts = $appDebts->groupBy('debt_type_id')->map(function ($item) {
return [
'total_amount' => $item->sum('amount'),
'debt_type' => $item->map(function ($item) {
return $item->debt_type->slug;
})->toArray(),
];
}); // <-- remove ->toArray() from here
$appDebts = $appDebts->map(function ($item, $key) {
return [
'debt_type_id' => $key
'debt_type' => $item["debt_type"][0], // assuming you want the first type !!
'total_amount' => $item["total_amount"],
];
})->toArray();
PS : This convert the given collection to tha wanted array for more performance tweaking consider editing the SQL query or the logic of getting appDebts
The only thing I can add to #Llopele's answer is to use keyBy() for easier data access:
$parsed = $collection->map(function ($item, $id) {
return [
'debt_id' => $id,
'debt_type' => collect($item['debt_type'])->first(),
'total_amount' => $item['total_amount']
];
})->values()->keyBy('debt_type')->toArray();
So now you can access data like this Arr::get($parsed, 'house_loan');

Laravel save multiple records

I've got an array within arrays and would like to add something to it.
$options = $request->options;
foreach ($options as $option) {
$option['poll_id'] = $this->id;
}
dd($options);
But for some reason it does not add to the array.
So I receive this:
array:1 [
0 => array:1 [
"name" => "testtest"
]
]
But I would expect this:
array:1 [
0 => array:1 [
"name" => "testtest",
"poll_id" => 1
]
]
You're not changing $options so foreach is destroying $option with each iteration. Try something like this instead:
$options = [];
foreach ($request->options as $key => $value) {
$options[$key]['poll_id'] = $this->id;
}
You should do it using the $key attribute on arrays
// Suppose your $request->options is like:
$options = [
0 => [
"name" => "testtest"
]
];
foreach ($options as $key => $option) {
$options[$key]['poll_id'] = 3; // Changing variable - $options here.
}
and it should work!
// $options would be like:
array:1 [▼
0 => array:2 [▼
"name" => "testtest"
"poll_id" => 3
]
]

Categories