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
Related
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();
I had a task where I needed to compare and filter two JSON arrays based on the same values using one column of each array. So I used this answer of this question.
However, now I need to compare two JSON arrays matching two, or even three columns values.
I already tried to use one map inside other, however, it isn't working.
The examples could be the ones in the answer I used. Compare db.code = file.code, db.name = file.nm and db.id = file.identity
var db = [
{
"CODE": "A11",
"NAME": "Alpha",
"ID": "C10000"
},
{
"CODE": "B12",
"NAME": "Bravo",
"ID": "B20000"
},
{
"CODE": "C11",
"NAME": "Charlie",
"ID": "C30000"
},
{
"CODE": "D12",
"NAME": "Delta",
"ID": "D40000"
},
{
"CODE": "E12",
"NAME": "Echo",
"ID": "E50000"
}
]
var file = [
{
"IDENTITY": "D40000",
"NM": "Delta",
"CODE": "D12"
},
{
"IDENTITY": "C30000",
"NM": "Charlie",
"CODE": "C11"
}
]
See if this works for you
%dw 2.0
output application/json
var file = [
{
"IDENTITY": "D40000",
"NM": "Delta",
"CODE": "D12"
},
{
"IDENTITY": "C30000",
"NM": "Charlie",
"CODE": "C11"
}
]
var db = [
{
"CODE": "A11",
"NAME": "Alpha",
"ID": "C10000"
},
{
"CODE": "B12",
"NAME": "Bravo",
"ID": "B20000"
},
{
"CODE": "C11",
"NAME": "Charlie",
"ID": "C30000"
},
{
"CODE": "D12",
"NAME": "Delta",
"ID": "D40000"
},
{
"CODE": "E12",
"NAME": "Echo",
"ID": "E50000"
}
]
---
file flatMap(v) -> (
db filter (v.IDENTITY == $.ID and v.NM == $.NAME and v.CODE == $.CODE)
)
Using flatMap instead of map to flatten otherwise will get array of arrays in the output which is cleaner unless you are expecting a possibility of multiple matches per file entry, in which case I'd stick with map.
You can compare objects in DW directly, so the solution you linked can be modified to the following:
%dw 2.0
import * from dw::core::Arrays
output application/json
var db = [
{
"CODE": "A11",
"NAME": "Alpha",
"ID": "C10000"
},
{
"CODE": "B12",
"NAME": "Bravo",
"ID": "B20000"
},
{
"CODE": "C11",
"NAME": "Charlie",
"ID": "C30000"
},
{
"CODE": "D12",
"NAME": "Delta",
"ID": "D40000"
},
{
"CODE": "E12",
"NAME": "Echo",
"ID": "E50000"
}
]
var file = [
{
"IDENTITY": "D40000",
"NM": "Delta",
"CODE": "D12"
},
{
"IDENTITY": "C30000",
"NM": "Charlie",
"CODE": "C11"
}
]
---
db partition (e) -> file contains {IDENTITY:e.ID,NM:e.NAME,CODE:e.CODE}
You can make use of filter directly and using contains
db filter(value) -> file contains {IDENTITY: value.ID, NM: value.NAME, CODE: value.CODE}
This tells you to filter the db array based on if the file contains the object {IDENTITY: value.ID, NM: value.NAME, CODE: value.CODE}. However, this will not work if objects in the file array has other fields that you will not use for comparison. Using above, you can update filter condition to check if an object in file array exist (using data selector) where the condition applies. You can use below to check that.
db filter(value) -> file[?($.IDENTITY==value.ID and $.NM == value.NAME and $.CODE == value.CODE)] != null
I am calling API and getting below output but from the output and i want to find the key based on value input and my input value is "vpc-tz" how to achieve this in ansible using json_query?
{
"json": {
"allScopes": [
{
"
"clusters": {
"clusters": [
{
"cluster": {
"clientHandle": "",
"type": {
"name": "ClusterComputeResource"
},
"universalRevision": 0,
"vsmUuid": "423B1819-9495-4F10-A96A-6D8284E51B29"
}
}
]
},
"controlPlaneMode": "UNICAST_MODE",
"description": "",
"extendedAttributes": [
],
"id": "vdnscope-6",
"isTemporal": false,
"isUniversal": false,
"name": "vpc-tz",
"nodeId": "85e0073d-0e5a-4f04-889b-42df771aebf8",
"objectId": "vdnscope-6",
"objectTypeName": "VdnScope",
"revision": 0,
"type": {
"name": "VdnScope"
},
"universalRevision": 0,
"virtualWireCount": 0,
"vsmUuid": "423B1819-9495-4F10-A96A-6D8284E51B29"
},
]
}
}
Here is a query which works:
json.allScopes[?name=='vpc-tz'].name
I use following terraform code to get a list of available db resources:
data "alicloud_db_instance_classes" "resources" {
instance_charge_type = "PostPaid"
engine = "PostgreSQL"
engine_version = "10.0"
category = "HighAvailability"
zone_id = "${data.alicloud_zones.rds_zones.ids.0}"
multi_zone = true
output_file = "./classes.txt"
}
And the output file looks like this:
[
{
"instance_class": "pg.x4.large.2",
"storage_range": {
"max": "500",
"min": "250",
"step": "250"
},
"zone_ids": [
{
"id": "cn-shanghai-MAZ1(b,c)",
"sub_zone_ids": [
"cn-shanghai-b",
"cn-shanghai-c"
]
}
]
},
{
"instance_class": "pg.x8.medium.2",
"storage_range": {
"max": "250",
"min": "250",
"step": "0"
},
"zone_ids": [
{
"id": "cn-shanghai-MAZ1(b,c)",
"sub_zone_ids": [
"cn-shanghai-b",
"cn-shanghai-c"
]
}
]
},
{
"instance_class": "rds.pg.c1.xlarge",
"storage_range": {
"max": "2000",
"min": "5",
"step": "5"
},
"zone_ids": [
{
"id": "cn-shanghai-MAZ1(b,c)",
"sub_zone_ids": [
"cn-shanghai-b",
"cn-shanghai-c"
]
}
]
},
{
"instance_class": "rds.pg.s1.small",
"storage_range": {
"max": "2000",
"min": "5",
"step": "5"
},
"zone_ids": [
{
"id": "cn-shanghai-MAZ1(b,c)",
"sub_zone_ids": [
"cn-shanghai-b",
"cn-shanghai-c"
]
}
]
}
]
And I want to get the one that's cheapest.
One way to do so is by sorting with storage-range.min, but how do I sort this list based on 'storage_range.min'?
Or I can filter by 'instance_class', but "alicloud_db_instance_classes" doesn't seem to like filter as it says: Error: data.alicloud_db_instance_classes.resources: : invalid or unknown key: filter
Any ideas?
The sort() function orders lexicographical and you have no simple key here.
You can use filtering with some code like this (v0.12)
locals {
best_db_instance_class_key = "rds.pg.s1.small"
best_db_instance_class = element( alicloud_db_instance_classes.resources, index(alicloud_db_instance_classes.resources.*.instance_class, best_db_instance_class_key) )
}
(Untested code)
Hi I want to merge two hashes into a json file which should look like this:
{
"name": "MS Suite",
"version": "2017.1.0",
"components": [
{
"code": "1x.2017",
"name": "microservice1",
"version": "1.1.3-1"
},
{
"code": "3x.2017",
"name": "microservice2",
"version": "1.1.15-1"
}
]
}
Please find below hash1:
{
"name": "MS Suite",
"version": "2017.1.0"
}
Please find below hash2 which is an array:
[
{
"code": "1x.2017",
"name": "microservice1",
"version": "1.1.3-1"
},
{
"code": "3x.2017",
"name": "microservice2",
"version": "1.1.15-1"
}
]
You're looking for Hash#[]=:
hash = {
"name": "MS Suite",
"version": "2017.1.0"
}
array = [
{
"code": "1x.2017",
"name": "microservice1",
"version": "1.1.3-1"
},
{
"code": "3x.2017",
"name": "microservice2",
"version": "1.1.15-1"
}
]
hash['components'] = array
hash
#=> {:name=>"MS Suite", :version=>"2017.1.0", "components"=>[{:code=>"1x.2017", :name=>"microservice1", :version=>"1.1.3-1"}, {:code=>"3x.2017", :name=>"microservice2", :version=>"1.1.15-1"}]}
To convert it to json:
require 'json'
hash.to_json
#=> "{\"name\":\"MS Suite\",\"version\":\"2017.1.0\",\"components\":[{\"code\":\"1x.2017\",\"name\":\"microservice1\",\"version\":\"1.1.3-1\"},{\"code\":\"3x.2017\",\"name\":\"microservice2\",\"version\":\"1.1.15-1\"}]}"