How to sort array of objects - javascript

I need your help to understand how to sort array of objects with another array inside each of object. I have response from api with array bunch of objects like below:
[
{
"name": "[C US Equity] CITIGROUP INC",
"stats": [
{
"label": "DTD",
"value": null
},
{
"label": "MTD",
"value": null
},
{
"label": "YTD",
"value": 0.0536530913792681
},
{
"label": 2016,
"value": 0.18102519526139493
},
{
"label": 2015,
"value": -0.012946569977188238
},
{
"label": 2014,
"value": null
}
]
}...
]
I should be sort it by value of label "YTD" exclude of null value. Any help are welcome

You can use array#sort method
var oldArray = [{
"name": "[C US Equity] CITIGROUP INC",
"stats": [{
"label": "DTD",
"value": null
},
{
"label": "MTD",
"value": null
},
{
"label": "YTD",
"value": 0.0536530913792681
},
{
"label": 2016,
"value": 0.18102519526139493
},
{
"label": 2015,
"value": -0.012946569977188238
},
{
"label": 2014,
"value": null
}
]
}];
oldArray[0].stats.sort(function(a, b) {
return a.label - b.label;
})
console.log(oldArray)

You can use collection sort method provided by lodash. https://lodash.com/docs/4.17.4#sortBy
var users = [{
"name": "[C US Equity] CITIGROUP INC",
"stats": [
{
"label": "DTD",
"value": null
},
{
"label": "MTD",
"value": null
},
{
"label": "YTD",
"value": 0.0536530913792681
},
{
"label": null,
"value": 0.18102519526139493
},
{
"label": "2015",
"value": -0.012946569977188238
},
{
"label": "dtd",
"value": null
}
]
}]
console.log(_.sortBy(users[0].stats, [function(o) { if(o.label){return  o.label.toUpperCase();} }]));
This takes case of null values too.

I think this post may help you.
Take a look of it, it teaches you about how compare works.
All you need to do is to put that JSON thing into an object array,
then compare the value of YTD(make two for-loops, result [i] .stats [j] .label === 'YTD') to make the array to re-order it.
A comparison function is work like below(extracted from the above link)
function CompareNumbers( v1, v2 ) {
if ( v1 < v2 ) return -1; // v1 goes nearer to the top
if ( v1 > v2 ) return 1; // v1 goes nearer to the bottom
return 0; // both are the same
}
when it return -1(or sometimes false), the former one will be pushed to the front of your array, meanwhile 1 or true will push the former one to the back. And 0 (means not true or false, or you can handle the exception by yourself, push back or forward) will happen nothing.
But becare if your array exist two 'YTD' labelled value, if it happens it will make two value to appear in the same data.
This may help you in sorting the data while you cannot directly get a sorted data from your db server.
Oh, forgot to say, the compare function can compare the whole object.(of course you need to extract something like this ---> object[index].['Something your needed']), not only numbers.

Related

Is there a way to display more than 5 buttons in Amazon lex-v2 response

This is my sessionState object
{
"sessionAttributes": {},
"dialogAction": {
"type": "ElicitSlot",
"slotToElicit": "flowName"
},
"intent": {
"name": "WelcomeIntent",
"confirmationState": "None",
"slots": {
"flowName": null
},
"state": "Fulfilled"
}
this is messages array
[
{
"contentType": "ImageResponseCard",
"content": "Some content",
"imageResponseCard": {
"title": "Choose option",
"subtitle": "options are",
"buttons": [
{
"text": "option1",
"value": "option1"
},
{
"text": "option2",
"value": "option2"
},
{
"text": "option3",
"value": "option3"
},
{
"text": "option4",
"value": "option4"
},
{
"text": "option5",
"value": "option5"
},
{
"text": "option6",
"value": "option6"
},
{
"text": "option7",
"value": "option7"
}
]
}
}
]
iam sending 7 buttons from lamda function, but lex is not accepting more than 5 buttons. It is giving error saying buttons should be between 0,5 index. Is there way to display more than 5 buttons in lex response.
As per the developer guide, ImageResponseCard supports a maximum of 5 button objects.
Array Members: Minimum number of 0 items. Maximum number of 5 items.
ImageResponseCard - AWS Lex V2 Developer Guide
I took the approach of conditionally eliciting different cards after a previous slot. In my case, choose a risk level (High, Medium, Low) and depending on which value, elicit either a High, Med, or low slot card prompt. Just a workaround.

How to sort three items in an array in a particular order?

This question is an extension from this one
I've created a cart to which items can be added or removed. At some point in my app I'm displaying this cart, which will have max 3 items. However, the order of the items change as I add/remove from the cart.
{cartItems.map( item => <p>{item.name || item.time}</p>)}
The items being added have a type property which could be used for setting an order:
[{
"id": "0",
"type": "service",
"name": "Painting",
}, {
"id": "0",
"type": "time",
"day": "today",
"time": "09:40",
}, {
"id": "0",
"type": "business",
"name": "Baron's Motel",
}]
So far a kind stranger has taught me how to use sort() for solving this problem with two items
function compare(a, b) {
if (a.type === b.type) return 0;
else if (a.type === 'time') return -1;
return 1;
}
how can I take this one level further and sort 3 items, always displaying object with 'time' type before 'service', and place 'business' at the end?
You can use an object or some other mechanism to store the weights of item type:
function compare(a, b) {
const weights = { time: 0, service: 1, business: 2 };
return weights[a.type] - weights[b.type];
}
You can make an array of the types in the specific order you want. And use the difference of indexes of the the current type inside that array.
const arr = [{
"id": "0",
"type": "service",
"name": "Painting",
},
{
"id": "0",
"type": "time",
"day": "today",
"time": "09:40",
},
{
"id": "0",
"type": "business",
"name": "Baron's Motel",
}]
let order = ['time', 'service', 'business'];
const res = arr.sort((a, b) => order.indexOf(a.type) - order.indexOf(b.type));
console.log(res)

Get data of JSON string

I need to get the title of interval but my function returns undefined.
Function
filterByCategories () {
return _.orderBy(this.meetups.filter(item => {
console.log('title: ' + JSON.stringify(item.interval.title, null, 4))
JSON (content of this.meetups):
[
{
"id": "-12345",
"title": "abcds",
"description": "Hello3",
"date": "2023-12-29",
"location": {
"color": "grey darken-2",
"icon": "not_interested",
"id": "none",
"title": ""
},
"creatorId": "abcd1234",
"time": "24:00",
"color": {
"color": "red darken-2",
"id": "06",
"title": "Ret"
},
"interval": {
"color": "green darken-2",
"icon": "local_activity",
"title": "Weekly",
"value": 3
},
"statusType": false,
"pause": false,
"pushNotification": false
}
]
How to read the title of interval?
Since the json is already parsed, you can simply just access it by it's property name. Keep in mind, the data is within an array so there will be multiple .interval.title. Using a for loop is probably a better option here unless you're after a certain index. If you are after a certain index, forget the for loop and just do json[0].interval.name (0 being the index you're after);
const json = [
{
"id": "-12345",
"title": "abcds",
"description": "Hello3",
"date": "2023-12-29",
"location": {
"color": "grey darken-2",
"icon": "not_interested",
"id": "none",
"title": ""
},
"creatorId": "abcd1234",
"time": "24:00",
"color": {
"color": "red darken-2",
"id": "06",
"title": "Ret"
},
"interval": {
"color": "green darken-2",
"icon": "local_activity",
"title": "Weekly",
"value": 3
},
"statusType": false,
"pause": false,
"pushNotification": false
}
];
for (let i = 0; i < json.length; i++) {
const meetup = json[i];
console.log(meetup.interval.title);
}
Try this, if there are multiple objects in meetups, you can use Array.map to iterate over the array of objects, and print out the value of the title property within interval?
this.meetups.map(obj => {
console.log(`title: ${obj['interval']['title']}`);
});
Or simply this, if there is only 1 object in meetups?
this.meetups[0]['interval']['title']
Demo:
const meetups =[{"id":"-12345","title":"abcds","description":"Hello3","date":"2023-12-29","location":{"color":"grey darken-2","icon":"not_interested","id":"none","title":""},"creatorId":"abcd1234","time":"24:00","color":{"color":"red darken-2","id":"06","title":"Ret"},"interval":{"color":"green darken-2","icon":"local_activity","title":"Weekly","value":3},"statusType":false,"pause":false,"pushNotification":false}];
meetups.map(obj => {
console.log(`title: ${obj['interval']['title']}`);
});
Regarding the code you have provided on your question, I am unsure why did you use Array.filter(), as what it does is that it returns a new array based on the callback function you have provided within filter(). In addition, stringifying it using JSON.stringify() will turn that array into a string, which kind of defeats the purpose of accessing the values within the array of objects.

get values in an array inside an array

I have a question here I want to get all the value of the values array inside this array.
const sample = [
{
"key": "sampleKey", "values":
[
{ "key": "insidesampleKey", "value": 2 },
{ "key": "insideofinside", "value": 2 }
]
},
{
"key": "sampleKey2", "values":
[
{ "key": "insideSampleKey2", "value": 1 }
]
},
{
"key": "samplkey3", "values":
[
{ "key": "insideofsampleKey3", "value": 1 }
]
}
]
So far, I can only print the first one console.log(sample[0].values[0].value). I appreciate with any helps. Thanks much and have a great weekend
I think flatMap may be the best way to deal with this.
sample.flatMap(outer => outer.values.map(inner => inner.value))
You can use reduce and concat to get a flat, single array.
const sample = [{"key":"sampleKey","values":
[{"key":"insidesampleKey","value":2},{"key":"insideofinside","value":2}]},
{"key":"sampleKey2","values":[{"key":"insideSampleKey2","value":1}]},
{"key":"samplkey3","values":[{"key":"insideofsampleKey3","value":1}]}]
var values = sample.reduce((acc, item) => acc.concat(item.values.map(v=> v.value)),[]);
console.log(values);
The easiest method is to use a flatMap over the array as below. You can use polyfill for browsers that don't support the same yet. Use MDN to learn more.
sample.flatMap(item => item.values.map(inner => inner.value))
If you want to print the other value properties, just map over the array, then look at the values array, then look at value, and finally use flat to get a single array:
const sample = [{
"key": "sampleKey",
"values": [{
"key": "insidesampleKey",
"value": 2
}, {
"key": "insideofinside",
"value": 2
}]
},
{
"key": "sampleKey2",
"values": [{
"key": "insideSampleKey2",
"value": 1
}]
},
{
"key": "samplkey3",
"values": [{
"key": "insideofsampleKey3",
"value": 1
}]
}
];
console.log(sample.map(e => e.values.map(x => x.value)).flat(1));

Create new array with deleted values (React Native)

I have an array like this one :
[
Object {
"hex": "#00b2b9",
"label": "text",
"value": "364",
},
Object {
"hex": "#50690e",
"label": "text",
"value": "354",
},
Object {
"hex": "#925fa3",
"label": "text",
"value": "355"
}]
I have another array with this :
Array [
"355",
"356"
]
I'm looking to create a the first array but without the objects containing value 355 and 356. I tried with .filter()... but I'm a newbie with JS & React Native :-)
I tried some stuffs but almost every time I recreate my Array only with the values (i'm losing the objects inside)...
What I want to do is :
If I found 355 and 356 in my First Array, I delete the objects with them and I recreate my array with the only object remaining (value 364)
I was thinking about sth like that :
myFirstArray.filter(item => item.value != mySecondArray.value) but it's not a success ...
Thanks for help
The previous answers involve iterating over your id's array many times.
A more performant solution would be to store the id's in a set and then use that combined with a filter to produce your new array.
const arr = [
{
"hex": "#00b2b9",
"label": "text",
"value": "364",
},
...,
{
"hex": "#925fa3",
"label": "text",
"value": "355"
}];
const ids = ["354", "355"];
const idSet = new Set(ids);
const output = arr.filter(e => !idSet.has(e.value));
var firstArray = [{
"hex": "#00b2b9",
"label": "text",
"value": "364",
},
{
"hex": "#50690e",
"label": "text",
"value": "354",
},
{
"hex": "#925fa3",
"label": "text",
"value": "355"
}]
var secondArray = [
"355",
"356"
]
var thirdArray = firstArray.filter(item => secondArray.includes(item.value))
console.log(thirdArray)
You are nearly there, just use Array#includes() to determine whether or not the value of an item is in the second array:
myFirstArray.filter(item => !mySecondArray.includes(item.value))
let myFirstArray = [{
"hex": "#00b2b9",
"label": "text",
"value": "364",
},
{
"hex": "#50690e",
"label": "text",
"value": "354",
},
{
"hex": "#925fa3",
"label": "text",
"value": "355"
}
]
let mySecondArray = [
"355",
"356"
]
console.log(
myFirstArray.filter(item => !mySecondArray.includes(item.value))
)

Categories

Resources