I am trying to grab a value of a key inside of an object in an array which itself is an object in an array.
Here is what it looks like:
var books = [
{
"title": "title1",
"author": "author1",
"users": [
{
"id": 1,
"name": "Isidro"
},
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 3,
"name": "Trinidad"
}
]
},
{
"title": "title2",
"author": "author2",
"users": [
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 5,
"name": "Beatriz"
},
{
"id": 6,
"name": "Rosario"
}
]
},
What I am trying to do, 2 things:
First:
when I click on a user name in the HTML, I want to match the name clicked with the same user name in all the objects it is present in.
Second:
display the title of the books this user name is present in.
For example: when I click on Jose Miguel I want to see the 2 books he has read.
At the moment I have this:
var btnUser = document.querySelectorAll(".individualUsers");
for (var i = 0; i < btnUser.length; i++) {
btnUser[i].addEventListener("click", function() {
var clickedUser = this.innerText
var userBooks = books
.filter(x => x.users.name.indexOf(clickedUser) > -1)
.map(x => ` <li>${x.title}</li> <li>${x.author}</li>`);
console.log(clickedUser);
});
}
My problem is x.users.name.indexOf(clickedUser)is not accessing the user name.
You need to search inside the users array as well, one neat way is to do so with Array.some that return true if some of the conditional is true.
const books = [{
"title": "title1",
"author": "author1",
"users": [{
"id": 1,
"name": "Isidro"
},
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 3,
"name": "Trinidad"
}
]
},
{
"title": "title2",
"author": "author2",
"users": [{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 5,
"name": "Beatriz"
},
{
"id": 6,
"name": "Rosario"
}
]
}
];
const clickedUser = 'Jose Miguel';
var userBooks = books
.filter(x => x.users.some(user => user.name.indexOf(clickedUser) > -1));
console.log(userBooks);
Related
I have an Object which is having some properties like this:
obj1={
"id": 2,
"description": "",
"operationIds": [
{
"id": 1,
"name": "Standard"
}
],
"ratingIds": [
{
"id": 1,
"name": "name1",
"description": "",
},
{
"id": 4,
"name": "name4",
"description": "",
},
{
"id": 8,
"name": "name8",
"description": "",
},
],
}
I want covert the array of objects (operationIds and ratingIds) inside the object to array of properties, I'm receiving this object and I want to apply the change on it and supply another method so it should look like this:
obj1={
"id": 2,
"description": "",
"operationIds": [
1
],
"ratingIds": [
1,
4,
8
],
"timestamp": "AAAAAAAGJ6c=",
"estimatedUtilReconciliationApplies": true
}
I was able to do it but in a verry ugly way, is there a more simple and clear way to accomplish this ?
let x = {...obj} as any;
let ar1 = x.operationIds;
const arr1= ar1.map(function (obj) {
return obj.id;
});
let ar2 = x.ratingIds;
const arr2= ar2.map(function (obj) {
return obj.id;
});
x.operatingEnvironmentIds = arr1;
x.thrustRatingIds = arr2;
You can use spread operator and map
let obj1={
"id": 2,
"description": "",
"operationIds": [
{
"id": 1,
"name": "Standard"
}
],
"ratingIds": [
{
"id": 1,
"name": "name1",
"description": "",
},
{
"id": 4,
"name": "name4",
"description": "",
},
{
"id": 8,
"name": "name8",
"description": "",
},
],
}
console.log({
...obj1,
operationIds:obj1.operationIds.map(elem => elem.id),
ratingIds:obj1.ratingIds.map(elem => elem.id),
})
And as a function
let obj1={
"id": 2,
"description": "",
"operationIds": [
{
"id": 1,
"name": "Standard"
}
],
"ratingIds": [
{
"id": 1,
"name": "name1",
"description": "",
},
{
"id": 4,
"name": "name4",
"description": "",
},
{
"id": 8,
"name": "name8",
"description": "",
},
],
}
let transform = (obj) => {
return({
...obj,
operationIds:obj.operationIds.map(elem => elem.id),
ratingIds:obj.ratingIds.map(elem => elem.id),
})
}
let transformed = transform(obj1)
console.log(transformed)
We loop the array and use the Object.assign() method to convert an array of objects to a single object. This merges each object into a single resultant object.
The Object.assign() method also merges the properties of one or more objects into a single object.
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 am looking for a way to replace a bunch of data in a JSON file without replacing another part of it:
{
"task": [
{
"id": 5,
"title": "dave",
"description": "test"
},
{
"id": 6,
"title": "fddsfsd",
"description": "fsdfsd"
},
{
"id": 7,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
},
{
"id": 8,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
}
],
"compteur": [
{
"id": 8
}
]
}
I manage to get everything that is in between the brackets of "task" in a variable.
My current issue is that I need to replace only what's inside the bracket and not affect the other parts of the file.
This is my code for retrieving the data of "tasks":
function RemoveNode(idToDelete) {
return jsonData.task.filter(function(emp) {
if (emp.id == idToDelete) {
return false;
}
return true;
});
}
var newData = RemoveNode(idToDelete);
arr1 = JSON.stringify(newData, null, 4);
console.log("arr1", arr1);
The console.log gives me:
arr1 [
{
"id": 5,
"title": "dave",
"description": "test"
},
{
"id": 6,
"title": "fddsfsd",
"description": "fsdfsd"
},
{
"id": 8,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
}
]
I actually need to replace this in the original JSON File but I have absolutely no idea how to achieve this.
You can use the spread operator, this will override the task data with your new filtered data
const removeNode = (idToDelete) =>
jsonData.task.filter((emp) => emp.id != idToDelete);
const newData = RemoveNode(idToDelete);
const updatedJSONData = {...jsonData, task: newData};
If your JSON file is not too large, you could consider changing the task array in your JS object (once you've read or imported it into your program) and then re-writing the json file.
JSON file before the program runs:
{
"task": [
{
"id": 5,
"title": "dave",
"description": "test"
},
{
"id": 6,
"title": "fddsfsd",
"description": "fsdfsd"
},
{
"id": 7,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
},
{
"id": 8,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
}
],
"compteur": [
{
"id": 8
}
]
}
Let's say we want to remove task objects with id=6. The code:
const myFileContents = require('./myFile.json');
const fs = require('fs');
const removeIdFromTasks = (taskList,idToRemove) => {
return taskList.filter(task => task.id!=idToRemove);
}
const writeJsonFile = (fileName,content) => {
fs.writeFile(fileName,content,(err) => {
if(err){
console.error(`Error in writing json file: ${e.message}`);
} else {
console.log(`File written`);
}
})
}
myFileContents.task = removeIdFromTasks(myFileContents.task,6);
writeJsonFile(`myFile.json`,JSON.stringify(myFileContents));
The same file after execution:
{
"task": [
{
"id": 5,
"title": "dave",
"description": "test"
},
{
"id": 7,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
},
{
"id": 8,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
}],
"compteur": [
{
"id": 8
}]
}
I have some data and I need a loop which creates 2 arrays...
So I first create the 2 arrays:
namelist = [];
countList = [];
{
"id": "622",
"name": "main",
"sub": {
"637": {
"id": "637",
"name": "name 1",
"stats": {
"count": 5
}
},
"638": {
"id": "638",
"name": "name 2",
"stats": {
"count": 10
}
}
}
}
The desired result for this example would be:
For namelist:
['name 1', 'name 2']
For countList:
[5, 10]
How can I do this?
var nameList = [];
var countList = [];
var myObj =
{
"id": "622",
"name": "main",
"sub": {
"637": {
"id": "637",
"name": "name 1",
"stats": {
"count": 5
}
},
"638": {
"id": "638",
"name": "name 2",
"stats": {
"count": 10
}
}
}
};
for(var key in myObj.sub){
nameList.push(myObj.sub[key].name);
countList.push(myObj.sub[key].stats.count);
}
console.log(nameList);
console.log(countList);
for(var key in obj.sub){
nameList.push(obj.sub[key].name);
countList.push(obj.sub[key].stats.count;
}
Object.keys may help you to walk through object properties. Example related to your object:
var namelist = [],
countList = [],
obj = {
"id": "622",
"name": "main",
"sub": {
"637": {
"id": "637",
"name": "name 1",
"stats": {
"count": 5
}
},
"638": {
"id": "638",
"name": "name 2",
"stats": {
"count": 10
}
}
}
};
Object.keys(obj.sub).forEach(function(item) {
namelist.push(obj.sub[item].name);
countList.push(obj.sub[item].stats.count);
});
console.log(namelist, countList);
Working example: https://jsfiddle.net/ry0zqweL/
Obviously, you can optimise it in many ways. It's just illustrating one of the many solutions.
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));