I have data
{
"id": 1000,
"price": "99,01USA",
},
{
"id": 1001,
"price": "100USA",
},
{
"id": 1002,
"price": "780USA",
},
{
"id": 1003,
"price": "20USA",
},
How I sort order by price (ASC , DESC)
You can alter it a little to parse price to integer and then sort it
You can create a dynamic sort function that sorts objects by their value that you pass:
function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
/* next line works with strings and numbers,
* and you may want to customize it to your needs
*/
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}
So you can have an array of objects like this:
var People = [
{Name: "Name", Surname: "Surname"},
{Name:"AAA", Surname:"ZZZ"},
{Name: "Name", Surname: "AAA"}
];
...and it will work when you do:
People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));
Actually this already answers the question. Below part is written because many people contacted me, complaining that it doesn't work with multiple parameters.
Multiple Parameters
You can use the function below to generate sort functions with multiple sort parameters.
function dynamicSortMultiple() {
/*
* save the arguments object as it will be overwritten
* note that arguments object is an array-like object
* consisting of the names of the properties to sort by
*/
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
/* try getting a different result from 0 (equal)
* as long as we have extra properties to compare
*/
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
}
Which would enable you to do something like this:
People.sort(dynamicSortMultiple("Name", "-Surname"));
Subclassing Array
For the lucky among us who can use ES6, which allows extending the native objects:
class MyArray extends Array {
sortBy(...args) {
return this.sort(dynamicSortMultiple(...args));
}
}
That would enable this:
MyArray.from(People).sortBy("Name", "-Surname");
Im trying to validate a terraform complex map. The map contains a list of objects with multiple attributes. I was trying to validate each attribute and unfortunately, it seems that whatever condition I put, it is ok. It's like the validation is always true.
Could anyone have a look and see what I'm doing wrong? Also, would it be possible to validate map keys?
variable "complexmap" {
type = map(object(
{
reference = string
type = string
count = string
}
))
default = {
"key1" = {
count = "5"
reference = "refcode1"
type = "novel"
},
"key2" = {
count = "2"
reference = "REFcode2"
type = "comics"
},
}
validation {
condition = (
alltrue([for v in var.complexmap : (
can(regex("[a-z0-9]{4,10}", v["reference"]))
&& v["count"] >= 2 && v["count"] < 10
&& (v["type"] == "novel" || v["type"] == "comics")
)])
)
error_message = "Validation of an object failed."
}
}
I have terraform with a resource being created with for. As is typical, each instance of this resource has several attributes. At the moment I have a series of map outputs for this resource group but each consists of only a single key-value pair. I would like my terraform output to include a list or map of maps or objects with all of the attributes grouped by resource instance. How do I do this without using flatten; zipmap etc to construct them from my current outputs? This example is with aws_route53_record but this is a generic query:
Current code
output "r53record_zonal_fqdn" {
value = {
for entry in aws_route53_record.zonal :
entry.name => entry.fqdn
}
}
output "r53record_zonal_records" {
value = {
for entry in aws_route53_record.zonal :
entry.name => entry.records
}
}
output "r53record_zonal_zone_id" {
value = {
for entry in aws_route53_record.zonal :
entry.name => entry.zone_id
}
}
As you would expect, this renders three maps with aws_route53_record.zonal.name as the key and the other attribute(s) as the value.
What I would like is to have these outputs grouped by resource with a predefined key for each value, e.g. (pseudocode):
output "r53record_zonal_zone_id" {
value = {
for entry in aws_route53_record.zonal : {
instance[count.index] {
"name" = entry.name
"fqdn" = entry.fqdn
"records" = entry.records
"zone_id" = entry.zone_id
}
}
}
}
Producing a map or list of maps for each instance.
How can this or something like it be done?
I created a random route53_record resource block with two "name" arguments in for_each loop and tried to output something close to what you were looking for.
Assuming "mydomain.com" is the domain in Route53 as example....
resource "aws_route53_record" "zonal" {
for_each=toset(["site1","site2"])
name = each.key
zone_id = "ABCDZONEIDSTRING"
type = "A"
ttl = "300"
records = ["192.168.1.10"]
}
output "test" {
value = {
for dns, details in aws_route53_record.zonal:
dns => ({"fqdn" = details.fqdn , "zone_id" = details.zone_id , "records" = details.records})
}
}
this will create output in this fashion..
test = {
"site1" = {
"fqdn" = "site1.mydomain.com"
"records" = [
"192.168.1.10",
]
"zone_id" = "Z0630117NTQNSYTXYQ4Z"
}
"site2" = {
"fqdn" = "site2.mydomain.com"
"records" = [
"192.168.1.10",
]
"zone_id" = "Z0630117NTQNSYTXYQ4Z"
}
}
Suppose you passed the name values with domain name, like below...
for_each=toset(["site1.mydomain.com","site2.mydomain.com"])
the output would look like
test = {
"site1.mydomain.com" = {
"fqdn" = "site1.mydomain.com"
"records" = [
"192.168.1.10",
]
"zone_id" = "ABCDMYZONEIDSTRING"
}
"site2.mydomain.com" = {
"fqdn" = "site2.mydomain.com"
"records" = [
"192.168.1.10",
]
"zone_id" = "ABCDMYZONEIDSTRING"
}
}
I have a JSON that have a JSONArray as a value in one of the json inside it. here is the example of it.
[
{
"id": 1,
"symptoms" : [{\"key\":\"sample1\",\"value\":5},{\"key\":\"sample2\",\"value\":5}]
},
{
"id": 2,
"symptoms" : [{\"key\":\"sample3\",\"value\":1}]
},
{ "id": 3,
"symptoms" : []
},
{
"id": 4,
"symptoms": [{\"key\":\"sample4\",\"value\":1}]
}
]
So what I am doing is that I am parsing the inner JSON and place it in a String Array. But whenever I look up to symptoms it skips the empty JSONArray. So whenever i print the String Array it goes like this (with the given sample on top) ["sample1", "sample2", "sample3", "sample4"]. But i want to do is to append an "" to the String Array whenever the JSONArray is empty so it should be like this ["sample1", "sample2", "sample3", "", "sample4"]. Anyone can help me with this? Here is my code
var arrayHolder: [String] = []
var idHolder: [Int] = []
for item in swiftyJSON.arrayValue {
idHolder.append(item["id"].intValue)
//for the inner JSON
let innerJSON = JSON(data: item["symptoms"].dataUsingEncoding(NSUTF8StringEncoding)!)
for symptoms in innerJSON.arrayValue {
arrayHolder.append(symptoms["key"].stringValue)
}
}
print(idHolder) // [1,2,3,4]
print(arrayHolder) // ["sample1","sample2","sample3","sample4"]
Just check if innerJSON is empty:
for item in swiftyJSON.arrayValue {
idHolder.append(item["id"].intValue)
//for the inner JSON
let innerJSON = item["symptoms"].arrayValue // non need to create a new JSON object
if innerJSON.isEmpty {
arrayHolder.append("")
} else {
for symptoms in innerJSON {
arrayHolder.append(symptoms["key"].stringValue)
}
}
}
I am doing a hotel search by entering the hotel names.Below is the valid JSON response. This is a response for one hotel search. I have run 15 threads and I have 14 more JSON response for different hotels similar to this one. In this response you can see "providers" and "results" that refer to the providers with array values. My requirement is to find out how many offers ie., results each provider has in total across all the 15 hotels.
"providers":
[
{
"MM_logofile":"agd.svg",
"MM_isOfficialWithoutLogo":false,
"code":"AGD",
"name":"Agoda.com",
"logo":"AGD.png",
"isOfficial":false
},
{
"MM_logofile":"ian.svg",
"MM_isOfficialWithoutLogo":false,
"code":"IAN",
"name":"Hotels.com",
"logo":"IAN-Other.png",
"isOfficial":false
},
{
"MM_logofile":"gar.svg",
"MM_isOfficialWithoutLogo":false,
"code":"GAR",
"name":"getaroom.com",
"logo":"GAR.png",
"isOfficial":false
},
{
"MM_logofile":"exp.svg",
"MM_isOfficialWithoutLogo":false,
"code":"EXP",
"name":"Expedia.dk",
"logo":"EXP-DK.png",
"isOfficial":false
},
{
"MM_logofile":"acc.svg",
"MM_isOfficialWithoutLogo":false,
"code":"ACC",
"name":"AccorHotels.com",
"logo":"ACC.png",
"isOfficial":true
},
],
"results":
[
{
"roomName":"Standard Twin Rm Special Offer - Best price guarantee",
"totalRate":918.0,
"isCheapestRate":true,
"hasFreeCancelation":false,
"inclusions":
[
],
"availableRooms":null,
"providerIndex":0,
"includesAllTaxes":false,
"excludedCharges":
[
0
],
"bookUri":"https://72750.api.hotelscombined.com/ProviderRedirect.ashx?key=0.11648360.-378376995.495.USD.123155627&source=202-0&a_aid=72750&brandID=177977"
},
{
"roomName":"Standard Double Rm Special Offer - Best price guarantee",
"totalRate":918.0,
"isCheapestRate":false,
"hasFreeCancelation":false,
"inclusions":
[
],
"availableRooms":null,
"providerIndex":0,
"includesAllTaxes":false,
"excludedCharges":
[
0
],
"bookUri":"https://72750.api.hotelscombined.com/ProviderRedirect.ashx?key=0.11648360.-378376995.496.USD.1523114518&source=202-1&a_aid=72750&brandID=177977"
},
{
"roomName":"Standard Double Room Hot Deal - Best price guarantee",
"totalRate":918.0,
"isCheapestRate":false,
"hasFreeCancelation":false,
"inclusions":
[
],
"availableRooms":null,
"providerIndex":1,
"includesAllTaxes":false,
"excludedCharges":
[
0
],
"bookUri":"https://72750.api.hotelscombined.com/ProviderRedirect.ashx?key=0.11648360.-378376995.497.USD.573302441&source=202-2&a_aid=72750&brandID=177977"
},
{
"roomName":"Standard Twin Room Hot Deal - Best price guarantee",
"totalRate":918.0,
"isCheapestRate":false,
"hasFreeCancelation":false,
"inclusions":
[
],
"availableRooms":null,
"providerIndex":2,
"includesAllTaxes":false,
"excludedCharges":
[
0
],
"bookUri":"https://72750.api.hotelscombined.com/ProviderRedirect.ashx?key=0.11648360.-378376995.498.USD.1523907592&source=202-3&a_aid=72750&brandID=177977"
},
{
"roomName":"Standard Room, 1 Double Bed",
"totalRate":926.2,
"isCheapestRate":false,
"hasFreeCancelation":false,
"inclusions":
[
],
"availableRooms":null,
"providerIndex":3,
"includesAllTaxes":false,
"excludedCharges":
[
0
],
"bookUri":"https://72750.api.hotelscombined.com/ProviderRedirect.ashx?key=0.13476094.-378377052.1210.USD.1325439035&source=202-4&a_aid=72750&brandID=177977"
},
],
Following is the beanshell code:
import java.util.HashMap;
import java.util.Map;
results_count = Integer.parseInt(vars.get("results_matchNr"));
providers_count = Integer.parseInt(vars.get("providers_matchNr"));
log.info("total results " + results_count);
Map results = new HashMap();
Map providers = new HashMap();
for(i=1; i<=providers_count; i++){
log.info("iteration " + i);
temp = vars.get("providers_"+i);
log.info("provider_name " + temp);
providers.put(i-1, temp);
}
log.info("providers: " + providers);
int provider_index = -1;
String provider_name = "";
for(i=1; i<=results_count; i++){
log.info("iteration " + i);
provider_index = Integer.parseInt(vars.get("results_"+i));
log.info("provider_index " + provider_index);
provider_name = providers.get(provider_index);
log.info("provider name :" + provider_name);
if(results.get(provider_name) == null){
log.info("ading key for the first time " + provider_name);
results.put(provider_name, 1);
}
else{
log.info("second time " + provider_name);
int existing = results.get(provider_name);
log.info("exisiting value " + existing);
int updateValue = existing+1;
log.info("updated value: " + updateValue);
results.put(provider_name, updateValue);
}
}
log.info("results-providers mapping " + results);
int threadNum = ctx.getThreadNum();
// if you want to log something to jmeter.log file
// Pass true if you want to append to existing file othewise false.
f = new FileOutputStream("G:\\naveen\\mywork\\testing\\performance\\tools\\jmeter\\examples\\result.csv", true);
p = new PrintStream(f);
this.interpreter.setOut(p);
String output = "thread number#" + threadNum + " " + results;
print(output);
f.close();
Add BeanShell PostProcessor to the sampler and add the above code.
Add JSONPATH Extractor to get the providers and add the following syntax:
$.providers[*].name
Add another JSONPATH Extractor to get the results/offers and add the following syntax:
$.results[*].providerIndex
Note: change the file location to store the results as per your machine in the beanshell code.
Following is the results which will be saved into the file:
thread number#0 {Expedia.dk=1, Agoda.com=2, Hotels.com=1, getaroom.com=1}
thread number#1 {Expedia.dk=1, Agoda.com=2, Hotels.com=1, getaroom.com=1}
// two rows for two threads. here, Agoda.com provider has two offers, so the count is 2 and remaining providers has one offer each.
Note: verified the script for 2 users. there will be two entries present in the results file (one thread -> one row). chnage the foramt as per your requirements on beanshell code (code related to file writing).