I have sample json, i need to sort based on the values using javascript/jquery.
I added example json code and expected output code in bellow.
For example with have this code :
var json = {
"users": {
"metrics": {
"e-f2e04fc7aa72": {
"order": 5,
"displayName": "User5"
},
"bb202c11-5d44-48a": {
"order": 1,
"displayName": "User2"
},
"a0d6e3afa2b5": {
"order": 3,
"displayName": "User3"
},
"46af13d22392856da": {
"order": 4,
"displayName": "User4"
},
"0c5f43cdd73b9cf623": {
"order": 2,
"displayName": "User2"
}
}
}
}
How can I sort this json to be like this :
var json = {
"users": {
"metrics": {
"bb202c11-5d44-48a": {
"order": 1,
"displayName": "User1"
},
"0c5f43cdd73b9cf623": {
"order": 2,
"displayName": "User2"
},
"a0d6e3afa2b5": {
"order": 3,
"displayName": "User3"
},
"46af13d22392856da": {
"order": 4,
"displayName": "User4"
},
"e-f2e04fc7aa72": {
"order": 5,
"displayName": "User5"
},
}
}
}
You can't sort the object, but you can create a sorted list from it.
var metricsSorted = [];
for (var key in json.users.metrics) {
var metric = json.users.metrics[key];
metric.id = key;
metricsSorted.push(metric);
}
metricsSorted.sort(function(a, b) {
return a.order - b.order;
});
console.log(metricsSorted);
First of all, you cannot sort an object, you can define your target json as array so it could be sorted.
Let's say, you can define you target json as :
var json = {
"users": {
"metrics": [
{ "id": "bb202c11-5d44-48a",
"order": 1,
"displayName": "User1"
},
{ "id": "0c5f43cdd73b9cf623",
"order": 2,
"displayName": "User2"
},
{ "id": "a0d6e3afa2b5",
"order": 3,
"displayName": "User3"
},
{ "id": "46af13d22392856da",
"order": 4,
"displayName": "User4"
},
{ "id": "e-f2e04fc7aa72",
"order": 5,
"displayName": "User5"
}
]
}
}
And then you can use below code to sort your original json into it as below:
var metrics = []
for(var id in json.users.metrics){
metrics.push({"id": id,"order":json.users.metrics[id].order,"displayName":json.users.metrics[id].displayName})
}
metrics.sort(function(a,b) { return a.order - b.order } );
json.users.metrics = metrics
//console.log(JSON.stringify(json))
You can iterate through the properties of metrics, using e.g. for .. in, and create a list of users. Then it can be sorted.
var users = []
var metrics = json.users.metrics
for (var userId in metrics) {
var user = metrics[userId];
user["userId"] = userId;
users.push(user);
}
In the format you expect, however, you cannot do it, as object properties cannot be sorted (as far as I know).
Related
I'm trying to filter some objects based on another array of objects. So I'm getting data from an API. These are for example receipts:
[
{
"id": 1,
"name": "test",
"category": {
"id": 1,
"name": "Cookies",
},
},
{
"id": 2,
"name": "test2",
"category": {
"id": 2,
"name": "Candy",
},
}
]
Then I'm trying to filter the objects on the category name based on another array of categories.
I've created a function for this:
function onSelectCategory(category) {
let receiptsList = receipts.filter((a) =>
a.category.includes(category.name)
);
setReceiptsView(receiptsList);
setSelectedCategory(category);
}
const category = [ { "id": 2, "name": "Candy" } ];
onSelectCategory(category);
When I run this function, I get an empty Array []. I can't really figure out what I'm doing wrong.
Since the param seems to be an array of objects, you need to use Array#some for comparison instead:
const receipts = [
{ "id": 1, "name": "test", "category": { "id": 1, "name": "Cookies" } },
{ "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];
const receiptsList = receipts.filter(({ category }) =>
categories.some(({ name }) => name === category.name)
);
console.log(receiptsList);
Another solution using Set:
const receipts = [
{ "id": 1, "name": "test", "category": { "id": 1, "name": "Cookies" } },
{ "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];
const categorySet = new Set(categories.map(({ name }) => name));
const receiptsList = receipts.filter(({ category }) =>
categorySet.has(category.name)
);
console.log(receiptsList);
Assuming that category (the parameter) is a string, the issue is that you are attempting to get the attribute name from the string, when you should be comparing the string to the object.
Try this:
a.category.name == category;
instead of
a.category.includes(category.name)
I may be wrong aboout assuming that category is a string, please clarify by telling us what the parameter category is equal to.
I have an object that has a whole host of arrays and properties. There is a property called targetProperty which appears in various places of the object.
I have a function where if the user clicks yes, every instance of that property needs to be reassigned to a new value.
The problem is the function that I used for assigning a new value doesn't work in this senario:
reassingPropertyInObj(obj, status) {
if (typeof obj === 'object' && obj !== null) {
obj.targetProperty = status;
for (const key in obj) {
this.handleExpandCollapseClick(obj[key], status);
}
}
},
Does anyone have a solution for this? Also can't use JSON.parse() or anything like that because the properties need to stay reactive for later reassignment if needed by the user.
Below is an example of one object:
{
"id": 16,
"ref_study_id": "3412333",
"title": "SomePersonNameOne",
"capabilities_available": [
{
"id": 75,
"name": "Clinical Data",
},
{
"id": 538,
"name": "RK's Capability",
}
],
"capabilities_impacted": [],
"businessImpact": {
"id": 2,
"name": "Medium"
},
"sites_impacted": [],
"sites_available": []
},
{
"id": 6,
"ref_study_id": "123124",
"title": null,
"capabilities_available": [
{
"id": 37,
"name": "Clinical Site Experience,
},
{
"id": 41,
"name": "Experience",
}
],
"capabilities_impacted": [
{
"id": 37,
"name": "Information Exchange",
"is_study_level": false,
"businessImpact": {
"id": 2,
"name": "Medium"
}
},
{
"id": 39,
"name": "IT/Data Experience",
"is_study_level": false,
"businessImpact": {
"id": 2,
"name": "Medium"
}
},
{
"id": 34,
"name": "Mgmt & Storage",
"is_study_level": false,
"businessImpact": {
"id": 3,
"name": "Minor"
}
}
],
"businessImpact": {
"id": 2,
"name": "Medium"
},
"sites_impacted": [],
"sites_available": []
},
And the property in question is businessImpact. As you can see it appears by itself as a property and inside array (and sometimes those arrays of arrays of their own).
I setup a function like:
arrayOfProperties.forEach((property) => {
obj[property].forEach((o) => {
o.businessImpact = newVal;
});
});
But of course it doesn't go deep enough.
I have absolutely no idea of which title I could write.
Actually, here is what I get from API :
[
{
"order": 1,
"role": {
"label": "singer"
},
"artist": {
"name": "AaRON"
}
},
{
"order": 1,
"role": {
"label": "author"
},
"artist": {
"name": "Simon Buret"
}
},
{
"order": 2,
"role": {
"label": "author"
},
"artist": {
"name": "Olivier Coursier"
}
},
{
"order": 1,
"role": {
"label": "composer"
},
"artist": {
"name": "John Doe"
}
}
]
And here is what I need to send :
"artist": {
"singer": [
"AaRON"
],
"author": [
"Simon Buret",
"Olivier Coursier"
]
}
Of course, the order property must be taken in account.
Example : Simon Buret is the first item because he has the order set to 1.
I have absolutely no idea how to implement that, I just did a map, but don't know what to put inside :/
this.artistControl.controls.map(artistControl => {
...
});
Is there a way to do what I need ?
Does this work for you:
let arr = [
{ "order": 1, "role": { "label": "singer" }, "artist": { "name": "AaRON" } },
{ "order": 1, "role": { "label": "author" }, "artist": { "name": "Simon Buret" } },
{ "order": 2, "role": { "label": "author" }, "artist": { "name": "Olivier Coursier" } },
{ "order": 1, "role": { "label": "composer" }, "artist": { "name": "John Doe" } }
];
let obj = {'artist': {}};
arr.forEach(a => {
obj['artist'][a.role.label] = obj['artist'][a.role.label] || [];
obj['artist'][a.role.label][a.order-1] = a.artist.name;
});
console.log(obj);
You could use reduce method with object as a accumulator param and then check if the key doesn't exist create it with empty array as value and then add names by order.
const data = [{"order":1,"role":{"label":"singer"},"artist":{"name":"AaRON"}},{"order":1,"role":{"label":"author"},"artist":{"name":"Simon Buret"}},{"order":2,"role":{"label":"author"},"artist":{"name":"Olivier Coursier"}},{"order":1,"role":{"label":"composer"},"artist":{"name":"John Doe"}}]
const result = data.reduce((r, {
role: { label },
artist: { name },
order
}) => {
if (name) {
if (!r[label]) r[label] = [];
r[label][order - 1] = name;
}
return r;
}, {})
console.log(result)
const array = [{"order":1,"role":{"label":"singer"},"artist":{"name":"AaRON"}},{"order":1,"role":{"label":"author"},"artist":{"name":"Simon Buret"}},{"order":2,"role":{"label":"author"},"artist":{"name":"Olivier Coursier"}},{"order":1,"role":{"label":"composer"},"artist":{"name":"John Doe"}}];
const result = array
.sort((item1, item2) => item1.order - item2.order)
.reduce((acc, { role, artist }) => ({
...acc,
artist: {
...acc.artist,
[role.label]: [
...(acc.artist[role.label] || []),
artist.name,
],
},
}), { artist: {} });
console.log(result);
Here is another approach with es5
const data = [{ "order": 1, "role": { "label": "singer" }, "artist": { "name": "AaRON" } }, { "order": 1, "role": { "label": "author" }, "artist": { "name": "Simon Buret" } }, { "order": 2, "role": { "label": "author" }, "artist": { "name": "Olivier Coursier" } }, { "order": 1, "role": { "label": "composer" }, "artist": { "name": "John Doe" } }];
var result = data.reduce(function(map, obj) {
map["artist"] = map["artist"] || {};
if (obj.role.label === 'author' || obj.role.label === 'singer') {
map["artist"][obj.role.label] = map["artist"][obj.role.label] || [];
map["artist"][obj.role.label][obj.order - 1] = obj.artist.name;
}
return map;
}, {});
console.log(result)
I'm trying to filter an array of objects where the filter is another array (of integers) which are values of properties of the first array. I've managed to make it work but I'm not sure if it's the best way. Since I'm a beginner in javascript, I'd appreciate any suggestions/improvements.
The items.json file contains an object with an array of objects. I want to filter all the objects (within that array) that have an id equal to the "ids" on the itemsids array.
code:
const itemsall = require('./items.json');
let itemsids = [1, 403, 3];
let filtereditems = [];
itemsids.forEach(id => {
itemsall.items.forEach(item => {
if (id === item.id) {
filtereditems.push(item);
}
});
});
items.json (a small part of it)
{
"items": [
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
},
{
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
}
]
}
output: (expected)
[
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 403,
"name": "Cool Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 3,
"name": "Ultraball",
"img": "http://www.serebii.net/pokemongo/items/ultraball.png"
}
]
Thanks!
You can use filter() and indexOf() to return filtered array.
var data = {
"items": [{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
}, {
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
}, {
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
}]
}
let itemsids = [1, 403, 3];
var result = data.items.filter(function(e) {
return itemsids.indexOf(e.id) != -1
})
console.log(result)
With ES6/ES7 you can use includes() like this.
var result = data.items.filter((e) => itemsids.includes(e.id));
Here is the my first JSON Array format...
[
{
"id": "1234",
"caption": "caption1"
},
{
"id": "2345",
"caption": "caption2"
},
{
"id": "3456",
"caption": "caption3"
}
]
and here is another JSON Array Format
[
[
{
"id": "1234",
"value": "value11"
},
{
"id": "2345",
"value": "value12"
},
{
"id": "3456",
"value": "value13"
}
],
[
{
"id": "1234",
"value": "value21"
},
{
"id": "2345",
"value": "value22"
},
{
"id": "3456",
"value": "value23"
}
]
]
The above mentioned Two JSON Arrays, i need to compare each one with Id and need to format a new JSON Array with caption and value using javascript.
[
[
{
"caption" : "caption1",
"value":"value11"
},
{
"caption" : "caption2",
"value":"value12"
},
{
"caption" : "caption3",
"value":"value13"
}
],
[
{
"caption" : "caption1",
"value":"value21"
},
{
"caption" : "caption2",
"value":"value22"
},
{
"caption" : "caption3",
"value":"value23"
}
]
]
Please help me out.
You can do it in many ways. Below I show two variants:
Option 1: Pure JavaScript
In this example the program preindex first array for faster access to it data, and then loops over second array with map() function to create new array of arrays:
// Create index version of first array
var aix = {};
for(var i=0;i<arr1.length;i++) {
aix[arr1[i].id] = arr1[i].caption;
}
// Loop over array of arrays
var res1 = arr2.map(function(arr22){
return arr22.map(function(a){
return {caption:aix[a.id], value:a.value};
}
});
Option 2: Using special SQL library (Alasql)
Here, you can JOIN to arrays automatically with special SQL statement:
var res2 = arr2.map(function(a){
return alasql('SELECT arr1.caption, a.[value] \
FROM ? a JOIN ? arr1 USING id',[a,arr1]);
});
You can try these variants in working snippet below or play with it in jsFiddle.
(Disclaimer: I am the author of Alasql)
var arr1 = [
{
"id": "1234",
"caption": "caption1"
},
{
"id": "2345",
"caption": "caption2"
},
{
"id": "3456",
"caption": "caption3"
}
];
var arr2 = [
[
{
"id": "1234",
"value": "value11"
},
{
"id": "2345",
"value": "value12"
},
{
"id": "3456",
"value": "value13"
}
],
[
{
"id": "1234",
"value": "value21"
},
{
"id": "2345",
"value": "value22"
},
{
"id": "3456",
"value": "value23"
}
]
];
// JavaScript version
var aix = {};
for(var i=0;i<arr1.length;i++) {
aix[arr1[i].id] = arr1[i].caption;
}
var res1 = arr2.map(function(arr22){
return arr22.map(function(a){
return {caption:aix[a.id], value:a.value};
});
});
document.getElementById("res1").textContent = JSON.stringify(res1);
// Alasql version
var res2 = arr2.map(function(a){
return alasql('SELECT arr1.caption, a.[value] FROM ? a JOIN ? arr1 USING id',[a,arr1]);
});
document.getElementById("res2").textContent = JSON.stringify(res2);
<script src="http://alasql.org/console/alasql.min.js"></script>
<p>Varian 1: JavaScript</p>
<div id="res1"></div>
<p>Variant 2: Alasql</p>
<div id="res2"></div>