I have a collection where I get the points for each player.
$rankings = Player::with(['rankings'])
->map(function($item){
return ['points' => $item->rankings->pluck('points')];
})->sortByDesc('total');
This gives me back the following:
[
{
"player": 5,
"points": [
4,
2,
1,
2,
2,
3
]
},
{
"player": 1,
"points": [
2,
3,
3,
4,
4,
4
]
},
{
"player": 10,
"points": [
1,
4,
2,
1,
1,
2
]
},
{
"player": 6,
"points": [
3,
1,
1,
3,
3,
1
]
}
]
How can I sort the collection so that the players who score the most points 1? The ones with the most 2 points remaining second and so on? And in case there are players tied in points 1, get those who have more points 2?
[
{
"player": 10,
"points": [
1,
4,
2,
1,
1,
2
]
},
{
"player": 6,
"points": [
3,
1,
1,
3,
3,
1
]
},
{
"player": 5,
"points": [
4,
2,
1,
2,
2,
3
]
},
{
"player": 1,
"points": [
2,
3,
3,
4,
4,
4
]
},
]
Thanks.
Related
I want to modify nested collection using group by.
This is sample collection
"document": [
{
"id": 1,
"company_id": 4,
"client_id": 1,
"status": 1,
"client": {
"id": 1,
"company_id": 4,
"name": "1663159185735-client"
},
"document_items": [
{
"id": 1,
"master_id": 5,
"text_value": "piyo",
},
{
"id": 2,
"master_id": 5,
"text_value": "fuga",
},
{
"id": 3,
"master_id": 3,
"text_value": "hoge",
}
]
}
]
I want to change like this.
"document": [
{
"id": 1,
"company_id": 4,
"client_id": 1,
"status": 1,
"client": {
"id": 1,
"company_id": 4,
"name": "1663159185735-client"
},
"document_items": [
5: [{
"id": 1,
"master_id": 5,
"text_value": "piyo",
},
{
"id": 2,
"master_id": 5,
"text_value": "fuga",
}
],
3: [{
"id": 2,
"master_id": 5,
"text_value": "fuga",
}
]
]
}
]
I try write below code;
$result->map(function ($v){
$v->documentItems = $v->documentItems->groupBy('master_id');
return $v;
});
but output key is documentItems not document_items
I changed to
$v->document_items = $v->documentItems->groupBy('master_id');
key is drawing_drawing_items but not groupby(simple array)
how to modify group by and preserve key case?
I changed to
$v->document_items = $v->documentItems->groupBy('master_id');
key is drawing_drawing_items but not groupby(simple array)
You should also change like this $v->document_items->groupBy('master_id')
The key is 'document_items' not 'documentItems'
i have an array like this with position disordered i want to order the position like 123 123 123 12
[{
"id": 1,
"name": "ASDAS",
"position": 1,
},
{
"id": 2,
"name": "ASDAS",
"position": 1,
},
{
"id": 3,
"name": "ASDAS",
"position": 3,
},
{
"id": 4,
"name": "ASDAS",
"position": 2,
},
{
"id": 5,
"name": "ASDAS",
"position": 2,
},
{
"id": 6,
"name": "ASDAS",
"position": 3,
},
{
"id": 7,
"name": "ASDAS",
"position": 2,
},
{
"id": 8,
"name": "ASDAS",
"position": 1,
}
]
i want the order like that
[{
"id": 1,
"name": "ASDAS",
"position": 1,
},
{
"id": 4,
"name": "ASDAS",
"position": 2,
},
{
"id": 3,
"name": "ASDAS",
"position": 3,
},
{
"id": 2,
"name": "ASDAS",
"position": 1,
},
{
"id": 5,
"name": "ASDAS",
"position": 2,
},
{
"id": 6,
"name": "ASDAS",
"position": 3,
},
{
"id": 8,
"name": "ASDAS",
"position": 1,
},
{
"id": 7,
"name": "ASDAS",
"position": 2,
}
]
The below should do the trick. I assume your data is an array of objects.
First I order the array by ID and then seperate the items by group. Finally, I merge all the groups 1 item at a time. There is probably a better way to acheive what you are after but thought this might be a good starting point.
This will adapt to the max position value. For example, if one of the data items has a position of 4 you would end up with a position order: 1234 123 123 123 12... etc
<?php
$input = [
(object)[
"id" => 1,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 2,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 3,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 4,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 5,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 6,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 7,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 8,
"name" => "ASDAS",
"position" => 1,
]
];
// Sort array by ID
usort($input, function($a, $b) {
return $a->id <=> $b->id;
});
$groups = [];
foreach ($input as $item) {
// Create new group array
if (!array_key_exists($item->position, $groups)) {
$groups[$item->position] = [];
}
// Add item to group
$groups[$item->position][] = $item;
}
// Sort groups by position
ksort($groups);
// Merge groups 1 item at a time
function merge_groups(&$groups, &$target) {
foreach ($groups as $position => $group) {
if (!empty($group)) {
$target[] = array_shift($groups[$position]);
} else {
unset($groups[$position]);
}
}
if (!empty($groups)) {
merge_groups($groups, $target);
}
}
// Our final result array
$ouput = [];
merge_groups($groups, $ouput);
var_dump($ouput);
Tested in PHP 7.
Solution with simple loops. Foreach searches for a specific position and then increases the position. The number of positions can be more than 3. Positions like 123 123 23 are also possible.
$input = [
(object)[
"id" => 1,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 2,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 3,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 4,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 5,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 6,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 7,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 8,
"name" => "ASDAS",
"position" => 1,
]
];
$minPos = min(array_column($input, "position"));
$arr = [];
$pos = $minPos;
while(true){
$found = false;
foreach($input as $key => $obj){
if($obj->position == $pos){
$arr[] = $obj;
unset($input[$key]);
++$pos;
$found = true;
}
}
if(empty($input)) break;
$minPos = min(array_column($input, "position"));
if(!$found AND $pos != $minPos){
$pos = $minPos;
}
}
var_dump($arr);
hi trying to get the values of two columns as arrays, something like this
"result": {
"time": [1, 2, 4, 5, 6],
"values": [5, 6, 7, 8, 9]
}
i was able to do it using:
$result['result'] = DB::table(TimeSignal::getTableName())->select([
'value',
DB::raw("(time * 0.001) as time")
])
->where('trip_id', $trip->id)
->where('signal_type_id', $timeSignalType->id)
->orderBy('time', 'asc')
->get();
then:
$timeSignalData = $result['result'];
$result['result']['time'] = $timeSignalData->pluck('time');
$result['result']['values'] = $timeSignalData->pluck('value');
but the pluck function taking so much time to make the objects as array is their some way to do this faster or can we do it form the query directly.
I think I can solve your problems with a macro I found in Refactoring to Collections.
Collection::macro('transpose', function () {
$items = array_map(function (...$items) {
return $items;
}, ...$this->values());
return new static($items);
});
Visually it's something like this:
[1,2] [1,3,5]
[3,4] => transpose => [2,4,6]
[5,6]
Get the values in a Collection
$queryCollection = DB::table(TimeSignal::getTableName())->select([
'value',
DB::raw("(time * 0.001) as time")
])
->where('trip_id', $trip->id)
->where('signal_type_id', $timeSignalType->id)
->orderBy('time', 'asc')
->get();
This is how it looks so far
# dump($queryCollection)
Illuminate\Support\Collection {
all: [
{
+"value": 5,
+"time": 1,
},
{
+"value": 6,
+"time": 2,
},
{
+"value": 7,
+"time": 4,
},
{
+"value": 8,
+"time": 5,
},
{
+"value": 9,
+"time": 6,
},
...
],
}
Map every row to an Array...
$rows = $queryCollection->map(function($item) {
return collect($item)->toArray();
}));
Now it looks like this
# dump($rows)
Illuminate\Support\Collection {
all: [
[
"value": 5,
"time": 1,
],
[
"value": 6,
"time": 2,
],
[
"value": 7,
"time": 4,
],
[
"value": 8,
"time": 5,
],
[
"value": 9,
"time": 6,
],
...
],
}
Now we transpose it.
$rows = $rows->transpose()
Which gives us
# dump($rows)
Illuminate\Support\Collection {
all: [
[
5,
6,
7,
8,
9
],
[
1,
2,
4,
5,
6,
],
]
}
And finally, we add the keys:
$result = collect(['values', 'time'])->combine($rows)
Which gives us, finally:
# dump($result)
Illuminate\Support\Collection {
all: [
"values" => [
5,
6,
7,
8,
9
],
"time" => [
1,
2,
4,
5,
6,
],
]
}
# dump($result['time'])
[
1,
2,
4,
5,
6,
]
# dump($result['values'])
[
5,
6,
7,
8,
9,
]
Less steps:
$queryCollection = DB::table(TimeSignal::getTableName())->select([
'value',
DB::raw("(time * 0.001) as time")
])
->where('trip_id', $trip->id)
->where('signal_type_id', $timeSignalType->id)
->orderBy('time', 'asc')
->get();
$result = collect(['values', 'time'])->combine($queryCollection->map(function ($item) {
return collect($item)->toArray();
})->transpose());
I currently have the below json response that the API is returning. I am able to return it using Laravel Eloquent. There are several users and each user has a several receipts. A receipt has types and status. I want to try to get the total sum amount for each receipt that is related to its type and status. I was able to return the below json response using
$this->user->with('receipts')->has('receipts')->get(['id', 'name']);
I have tried using multiple laravel collections methods https://laravel.com/docs/5.8/collections#available-methods But I am still unable to get the desired response.
[
{
"id": 1,
"name": "kent",
"receipts": [
{
"id": 1,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 100
},
{
"id": 2,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 100
},
{
"id": 3,
"user_id": 1,
"type_id": 2,
"status": 1,
"amount": 50
},
{
"id": 4,
"user_id": 1,
"type_id": 2,
"status": 0,
"amount": 30
},
{
"id": 5,
"user_id": 1,
"type_id": 2,
"status": 0,
"amount": 30
},
{
"id": 6,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 20
},
{
"id": 7,
"user_id": 1,
"type_id": 1,
"status": 1,
"amount": 10
}
]
},
{
"id": 2,
"name": "allison",
"receipts": [
{
"id": 9,
"user_id": 2,
"type_id": 1,
"status": 0,
"amount": 20
}
]
}
]
I expect to get this:
[
{
"id": 1,
"name": "kent",
"receipts": [
{
"performance and deleted": 220,
"performance and not deleted": 10,
"project and deleted": 60,
"project and deleted": 50
}
]
},
{
"id": 2,
"name": "allison",
"receipts": [
{
"performance and deleted": 20,
"performance and not deleted": 0,
"project and deleted": 0,
"project and not deleted": 0
}
]
}
]
My main concern is to use laravel collection methods and easy to read code to get my expected result
In this way, I believe you get your expected result with nice readable code.
I'll assume that you have $users variable which contains a list of users in collection (And probably the receipts are already loaded).
// You need to name the keys as you desire. (I can't figure out the labels by the type_id and status numbers).
$statusPair = collect([
'performance and deleted' => [
'type_id' => 1,
'status' => 0,
],
'something' => [
'type_id' => 1,
'status' => 1,
],
'something 2' => [
'type_id' => 2,
'status' => 0,
],
'something 3' => [
'type_id' => 2,
'status' => 1,
],
]);
$data = $users->map(function ($user) use ($statusPair) {
$receipts = $user->receipts;
$sums = $statusPair->mapWithKeys(function ($pair, $statusLabel) use ($receipts) {
$filtered = $receipts;
foreach ($pair as $key => $value) {
$filtered = $filtered->where($key, $value);
}
$sum = $filtered->sum('amount');
return [
$statusLabel => $sum,
];
});
return [
'id' => $user->id,
'name' => $user->name,
'receipts' => $sums->toArray(),
];
});
i think this will help
$user->receipts->sum('amount');
I want to calculate avg in laravel using three table joins I've joined the tables perfectly and got the response from it but now I want to calculate the avg as well as count from the response I have got and then pass it to API response what should I do to achieve this?
Query i have tried
$individualScore= StatisticsMaster::with(['ratings',])->where('ratingsFor',$request->profileId)->get();
StatisticsMaster.php
public function ratings() {
return $this->hasMany(StatisticsChild::class,'statisticsMasterId','statisticsMasterId')->with('score');
}
StatisticsChild.php
public function score() {
return $this->belongsTo(Skill::class,'skillId','skillId');
}
public function getSkillNameAttribute(){
return $this->score->skillName;
}
DB Structure I have
tblSkills
->skillId
->skillName
->skillStatus
tblStatisticsMaster
->statisticsMasterId
->ratingsFor
->ratingsBy
->status
tblStatisticsChild
->statisticsChildId
->skillId
->statisticsMasterId
->individualScore
->statisticsStatus
I have got this response
{
"meta": {
"code": "200",
"message": "Skill Fetched Successfully."
},
"data": {
"skills": [
{
"statisticsMasterId": 1,
"ratingsFor": 1,
"ratingsBy": 6,
"score": 60.8,
"ratings": [
{
"skillId": 1,
"individualScore": 86,
"statisticsStatus": 1,
"skillName": "Shooting"
},
{
"skillId": 2,
"individualScore": 70,
"statisticsStatus": 1,
"skillName": "Dribbling"
},
{
"skillId": 3,
"individualScore": 54,
"statisticsStatus": 1,
"skillName": "Passing"
},
{
"skillId": 4,
"individualScore": 44,
"statisticsStatus": 1,
"skillName": "Defense"
},
{
"skillId": 5,
"individualScore": 50,
"statisticsStatus": 1,
"skillName": "Good Teammate"
}
]
},
{
"statisticsMasterId": 2,
"ratingsFor": 1,
"ratingsBy": 2,
"score": 52,
"ratings": [
{
"skillId": 1,
"individualScore": 50,
"statisticsStatus": 1,
"skillName": "Shooting"
},
{
"skillId": 2,
"individualScore": 50,
"statisticsStatus": 1,
"skillName": "Dribbling"
},
{
"skillId": 3,
"individualScore": 60,
"statisticsStatus": 1,
"skillName": "Passing"
},
{
"skillId": 4,
"individualScore": 50,
"statisticsStatus": 1,
"skillName": "Defense"
},
{
"skillId": 5,
"individualScore": 50,
"statisticsStatus": 1,
"skillName": "Good Teammate"
}
]
}
]
}
}
and the response I want.
{
"meta": {
"code": "200",
"message": "Skill Fetched Successfully."
},
"data": {
"skills": [
{
"statisticsMasterId": 1,
"ratingsFor": 1,
"ratingsBy": 6,
"score": 56.4,
"ratings": [
{
"skillId": 1,
"individualScore": 86,
"statisticsStatus": 1,
"skillName": "Shooting"
},
{
"skillId": 2,
"individualScore": 70,
"statisticsStatus": 1,
"skillName": "Dribbling"
},
{
"skillId": 3,
"individualScore": 54,
"statisticsStatus": 1,
"skillName": "Passing"
},
{
"skillId": 4,
"individualScore": 44,
"statisticsStatus": 1,
"skillName": "Defense"
},
{
"skillId": 5,
"individualScore": 50,
"statisticsStatus": 1,
"skillName": "Good Teammate"
}
]
}
]
}
}
where all the individual score contains the avg of all the ratings I'm using eloquent I want to do this in eloquent itself. how can I achieve this?
Thanks in advance :)