I have this this JSON.
{
"animals": [{
"name": "Cumi-Cumi",
"data": 1000
}, {
"name": "Udang",
"data": 300
}, {
"name": "Baranang",
"data": 12000
}, {
"name": "Cumi-Cumi",
"data": 1500
}, {
"name": "Udang",
"data": 500
}, {
"name": "Baranang",
"data": 17000
}, {
"name": "Cumi-Cumi",
"data": 2500
}]
}
How can I group the data key by its name, to be like this:
{
"animals": [{
"name": "Cumi-Cumi",
"data": [
1000, 1500, 2500
]
},
{
"name": "udang",
"data": [
300, 500
]
},
{
"name": "Baranang",
"data": [
12000, 17000
]
}
]
}
It might be because I'm tired, but I can't figure out how to make this more concise...
This is a start for you anyway.
$json = '{
"animals": [{
"name": "Cumi-Cumi",
"data": 1000
}, {
"name": "Udang",
"data": 300
}, {
"name": "Baranang",
"data": 12000
}, {
"name": "Cumi-Cumi",
"data": 1500
}, {
"name": "Udang",
"data": 500
}, {
"name": "Baranang",
"data": 17000
}, {
"name": "Cumi-Cumi",
"data": 2500
}]
}';
// Start by decoding the JSON (I assume it comes as a string, if not, then ignore this).
$collection = collect(json_decode($json, true))
// Now iterate over the keys (you only have one key (animals), but I wanted to be safe).
->map(function ($item) {
// Convert the sub arrays into a Collection, then group the data against each animal name.
// Then map (iterate) over each of the animals, one at a time.
return collect($item)->groupBy('name')->map(function ($animal) {
// Reduce each animal into a single entry.
return $animal->reduce(function ($carry, $data) {
// Use the name of the animal, then push the data onto the end. Feel free to sort at this point too!
$carry['name'] = $data['name'];
$carry['data'][] = $data['data'];
return $carry;
});
// Finally, I reset the groupBy keys to ensure it matches your desired output.
})->values();
});
JustCarty's solution is probably better, but I wanted to post mine anyways.
// get json string
$json = <<<JSON
{
"animals": [{
"name": "Cumi-Cumi",
"data": 1000
}, {
"name": "Udang",
"data": 300
}, {
"name": "Baranang",
"data": 12000
}, {
"name": "Cumi-Cumi",
"data": 1500
}, {
"name": "Udang",
"data": 500
}, {
"name": "Baranang",
"data": 17000
}, {
"name": "Cumi-Cumi",
"data": 2500
}]
}
JSON;
$result = collect(json_decode($json, true)) // transform $json into a collection
->map(function ($item) { // map over it
return collect($item); // make the animals array a collection
})
->map(function ($animals) { // map over it
return $animals
->unique('name') // leave only uniquely named animals
->map(function ($item) use ($animals) { // map over them
return [
'name' => $item['name'],
'data' => $animals->where('name', $item['name'])->pluck('data')->all()
]; // replace their 'data' values by the array of 'data' from each unique animal.
});
})
->toJson(); // turn back to json string
Using PHP 7.4 shorthand closures:
$results = collect(json_decode($json, true))
->map(fn($item) => collect($item))
->map(fn($item) => $item->unique('name')->map(fn($animal) => [
'name' => $animal['name'],
'data' => $item->where('name', $animal['name'])->pluck('data')->all()
]))
->toJson();
Related
Controllers/Komic Controller
public function search($value)
{
// Query Wildcards and Resources
$result = new KomikCollection(Komik::where('judul', 'like', '%'. $value .'%')->paginate(2));
return $result;
}
its fine when i directly return the $result
{
"data": [],
"links": {
"first": "http://localhost:8000/api/komik/a?page=1",
"last": "http://localhost:8000/api/komik/a?page=2",
"prev": null,
"next": "http://localhost:8000/api/komik/a?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 2,
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
{
"url": "http://localhost:8000/api/komik/a?page=1",
"label": "1",
"active": true
},
{
"url": "http://localhost:8000/api/komik/a?page=2",
"label": "2",
"active": false
},
{
"url": "http://localhost:8000/api/komik/a?page=2",
"label": "Next »",
"active": false
}
],
"path": "http://localhost:8000/api/komik/a",
"per_page": 2,
"to": 2,
"total": 4
}
}
but when i'll return it using helpers/response
public function search($value)
{
// Query Wildcards and Resources
$result = new KomikCollection(Komik::where('judul', 'like', '%'. $value .'%')->paginate(2));
// send response
return response()->json($result, 200);
}
the meta and link on the json response will be disapppear and return result like this
{
"id": 1,
"title": "Spare me, Great Lord !"
},
{
"id": 2,
"title": "I'm An Evil God"
}
I want the response include the meta and link tags, how do i fix this?
If you want to meta data with response then you must need to add ->response()->getData(true) in collection results.
So your final function looks like :
public function search($value)
{
// Query Wildcards and Resources
$result = new KomikCollection(Komik::where('judul', 'like', '%'. $value .'%')->paginate(2))->response()->getData(true);
// send response
return response()->json($result, 200);
}
When I execute following graphQL query which has only one function and I get output which is shown below.
I want output which has largest ID or the latest timestamp.
It is possible by making change in API but my constraint is not to make any change in API and have enhance the query only, Please help me how can I achieve my goal/ desired output
Input
query getAllCriticalevent{
getAllCriticalevent(patientId: 95)
{
id
startTime
}
}
Output
{
"data": {
"getAllCriticalevent": [
{
"id": "107",
"startTime": "2019-06-14 12:47:57.0"
},
{
"id": "1464",
"startTime": "2019-10-10 16:08:35.0"
},
{
"id": "1465",
"startTime": "2019-10-10 16:09:09.0"
},
{
"id": "1466",
"startTime": "2019-10-10 16:09:44.0"
},
{
"id": "1469",
"startTime": "2019-10-10 16:11:28.0"
},
{
"id": "1470",
"startTime": "2019-10-10 16:12:03.0"
},
{
"id": "1484",
"startTime": "2019-10-10 16:20:09.0"
}
]
}
}
My expected output is this
{
"startTime": "2019-10-10 16:20:09.0"
}
or
{
"id": "1484",
"startTime": "2019-10-10 16:20:09.0"
}
One way to do this is to add a column to the Type definition, then return it from your resolver.
In Laravel (not Java), the definition:
'max' => [
'type' => Type::int(),
'description' => 'The highest score achieved'
],
and a separate query in the ORM resolver (getMaxAttribute() is referenced as simply .max()):
public function getMaxAttribute() {
return DB::table('players')->max('score');
}
will return the max for a desired column. You request the column by name in GraphQL, just like normal (eg. "{ ... max }").
I have $balance that is returned from another function like this:
$balance = {
"data": [
{
"name": "ABS",
"y": 1450
},
{
"name": "PBT",
"y": 1200
},
{
"name": "Краситель",
"y": 1000
},
{
"name": "PP",
"y": 750
}
]
}
And I have also collection called $statistics like this:
$statistics = [
{
"name": "ABS",
"data": []
},
{
"name": "PP",
"data": []
},
{
"name": "PBT",
"data": []
},
{
"name": "Краситель",
"data": []
}
]
What I'm trying to do is pushing all y 's of $balance to corresponding $statistics by matching their name.
Here is short description of my code:
foreach ($balance["data"] as $firm){
$statistics->firstWhere('name', $firm->name)['data']->push($firm->y);
}
However, I'm getting Call to a member function push() on null error. Can anyone help me find out the problem
I'm quite new to Laravel,
Let's say I have 2 tables: main_sport and sub_sport. These two tables have a one-to-many relationship. 1 sport can have many sub sports.
I want the following json format
{
"success": "1",
"sports": [
"id": 1,
"name_of_categories": "Popular Sports",
"sub_sports:[
{
"id": 1,
"name_sub_sport_category": "Badminton"
},
{
"id": 2,
"name_sub_sport_category": "Football"
},
{
"id": 3,
"name_sub_sport_category": "Cricket"
},
]
]
"sports":[
"id": 2,
"name_of_categories": "Team Sports",
"sub_sports:[
{
"id": 4,
"name_sub_sport_category": "Badminton"
},
{
"id": 5,
"name_sub_sport_category": "Football"
},
]
]
}
I try for this function and i am getting following result
public function fetch()
{
$query= DB::table('details')
->join('table_sub_sport_category','table_sub_sport_category.id','=','details.sub_id')
->join('table_main_sport_category','table_main_sport_category.id','=','details.main_id')
->select(DB::raw('table_main_sport_category.id as id'),'table_main_sport_category.name_of_categories','table_sub_sport_category.name_sub_sport_category')
->get()
return response()->json(['success' =>'1','data'=>$query]);
}
{
"success": "1",
"data": [
{
"id": 1,
"name_of_categories": "Popular Sports",
"name_sub_sport_category": "Badminton"
},
{
"id": 1,
"name_of_categories": "Popular Sports",
"name_sub_sport_category": "Football"
},
{
"id": 1,
"name_of_categories": "Popular Sports",
"name_sub_sport_category": "Cricket"
},
]
}
Could you help me to get the desired result?
You should define sub_sport in the main sport Model like this:
class Sport extends Model{
public function sub_sport(){
return $this->hasMany(SubSport::class);
}
}
And in your controller you should write this:
$data = Sport::with('sub_sport')->get();
Use below code
$query= DB::table('details')
->join('table_sub_sport_category','table_sub_sport_category.id','=','details.sub_id')
->join('table_main_sport_category','table_main_sport_category.id','=','details.main_id')
->select(DB::raw('table_main_sport_category.id as id'),'table_main_sport_category.name_of_categories','table_sub_sport_category.name_sub_sport_category')
->get()
return Response::json([
'status' => 'error',
'sports' => $query
], 200);
Pushing nested data into a Map inside a List
Can anyone tell me:
How do i push a task to either of these users (List items) ideally by specific user id?
Thanks in advance.
My code:
const initialState = Immutable.List([
Immutable.Map({
"id": 1,
"name": "Abe Bell",
"tasks": [
{
"id": 1,
"title": "Get haircut",
"status": false
}
]
}),
Immutable.Map({
"id": 2,
"name": "Chad Dim",
"tasks": [
{
"id": 2,
"title": "Get real job",
"status": false
}
]
})
])
First, the way you're building this structure, the tasks array will not be an immutable instance, I think that is not what you want, you can use Immutable.fromJS to transform all the nested arrays and maps into a Immutable instance.
The way your data is structured you'll have to navigate through the list of users and perform the update when the id matches.
One way of doing that is using map
const initialState = Immutable.fromJS([
{
"id": 1,
"name": "Abe Bell",
"tasks": [
{
"id": 1,
"title": "Get haircut",
"status": false
}
]
},
{
"id": 2,
"name": "Chad Dim",
"tasks": [
{
"id": 2,
"title": "Get real job",
"status": false
}
]
}
]);
let userId = 2;
let newState = initialState.map(user => {
if (user.get('id') !== userId) {
return user;
}
return user.update('tasks', tasks => {
return tasks.push(Immutable.fromJS({
id: 3,
title: "new task",
status: false
}))
});
});
Although this will do what you want,I think you should change your data to a map instead of a list if this kind of operation is something recurrent in your application. This will make things easier and faster.
const initialState = Immutable.fromJS({
"1": {
"id": 1,
"name": "Abe Bell",
"tasks": [
{
"id": 1,
"title": "Get haircut",
"status": false
}
]
},
"2": {
"id": 2,
"name": "Chad Dim",
"tasks": [
{
"id": 2,
"title": "Get real job",
"status": false
}
]
}
});
let userId = "2";
let newState = initialState.updateIn([userId, 'tasks'], tasks => {
return tasks.push(Immutable.fromJS({
id: 3,
title: "new task",
status: false
}));
});