Remove item from items array and return new list array
list: [
{
"id": 1,
"name": "john",
"items": [
{
"id": 2,
"name": "michael",
},
{
"id": 3,
"name": "mohamed",
}
}]
Your question is not at all clear. You want to remove item from items array, but with respect to what you haven't mentioned. So I provided that condition myself. My code removes items based on the given id. If id is 2 the object inside the items array removes the object which has the id property set to 2.
var list=
[
{ "id": 1, "name": "john", "items":
[ { "id": 2, "name": "michael", },
{ "id": 3, "name": "mohamed", } ]}]
var id=2;
var r=list.forEach((w)=>{
w.items.forEach((u)=>{
if(u.id==id)
{w.items.splice(w.items.indexOf(u),1);}
})
})
console.log(list[0].items[0]);
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 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);
I have some data looking like:
var items = [
{ "id" : 1,
"title" : "this",
"groups" : [
{"id" : 1,
"name" : "groupA"},
{"id" : 2,
"name" : "groupB"}
]
},
{ "id" : 2,
"title" : "that",
"groups" : [
{"id" : 1,
"name" : "groupA"},
{"id" : 3,
"name" : "groupC"}
]
},
{ "id" : 3,
"title" : "other",
"groups" : [
{"id" : 3,
"name" : "groupC"},
{"id" : 2,
"name" : "groupB"}
]
}]
And I want to filter based on the group ids but I'm having trouble even accessing them - item.group returns the whole object and doing anything else (i.e. item.groups.id) returns a null or undefined value.
Any help about how to do this would be great. Essentially I want to filter the array to include all items that are in a specific group.
Thanks
Try this:
group3Items = items.filter(item => item.groups.findIndex(group => group.id==3) > -1)
You can do like this
var items = [{
"id": 1,
"title": "this",
"groups": [{
"id": 1,
"name": "groupA"
}, {
"id": 2,
"name": "groupB"
}]
}, {
"id": 2,
"title": "that",
"groups": [{
"id": 1,
"name": "groupA"
}, {
"id": 3,
"name": "groupC"
}]
}, {
"id": 3,
"title": "other",
"groups": [{
"id": 3,
"name": "groupC"
}, {
"id": 2,
"name": "groupB"
}]
}]
// A filter function to filter out the matched value
function filterArray(array, val) {
return array.filter(function(elem) {
return elem.id === val; // filtering by Id
})
}
// first filtering the original items array, & will get the object where id is 1
var obj = filterArray(items, 1);
//the previous result will return an array,
//so doing obj[0] which will give the first index.
//obj[0].groups will be an array again
var filterGroup = filterArray(obj[0].groups,1) // will be an array which contains the matched group
DEMO
Use:
Array.prototype.map to create a new array mapping every item in the array to a new object by
cloning every item using the spread operator* and override the groups key with a new array made from the original by using
Array.prototype.filter to keep only the objects with the correct id.
*need a transpiler such as babel or typescript though
OR
If you wanted to flatten the structure, then you could use Array.prototype.reduce to combine the arrays.
The code below has two outputs:
one keeps the original structure but filters out the items in the group that don't have an id of 3.
one flattens the structure and outputs just one array.
const items = [{
"id": 1,
"title": "this",
"groups": [{
"id": 1,
"name": "groupA"
},
{
"id": 2,
"name": "groupB"
}
]
},
{
"id": 2,
"title": "that",
"groups": [{
"id": 1,
"name": "groupA"
},
{
"id": 3,
"name": "groupC"
}
]
},
{
"id": 3,
"title": "other",
"groups": [{
"id": 3,
"name": "groupC"
},
{
"id": 2,
"name": "groupB"
}
]
}
];
const filteredRemovingGroups = items.map(item => ({
...item,
groups: item.groups.filter(subItem => subItem.id === 3)
}));
const filterAndFlatten = items.map(item =>
item.groups.filter(subItem => subItem.id === 3)
).reduce((combinedArr, arr) => [...combinedArr, ...arr], [])
console.log('filteredRemovingGroups', filteredRemovingGroups);
console.log('filterAndFlatten', filterAndFlatten);
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));
It's confusing to try to explain, but I want to be able to add a list of skill sets to different people objects that are in their own list.
For example:
I have a Json object of people:
"people": [
{
"id": 1,
"name": "Tony Rogers",
},
{
"id": 2,
"name": "Steven Grant",
},
{
"id": 3,
"name": "Peter Wilson",
},
]
and then I have a list of skills that I want to match up with them:
"skills": [
{
"id": 1,
"name": "Engineering",
"personId": 1
},
{
"id": 2,
"name": "Painting",
"personId": 2
},
{
"id": 3,
"name": "Chemistry",
"personId": 3
},
{
"id": 4,
"name": "Physics",
"personId": 1
},
]
but I am unsure how to get the output I want by looping through both lists. I would preferably like to append a "skills" section onto each person that contains all of their skills.
I thought I could do something along the lines of
people.forEach(function(person){
skills.forEach(function(skill){
if(skill.personId == person.id){
person['skills'] = {"name" : skill.name};
}
});
});
but it repeats a person multiple times rather than adding to their own skill list.
You need an array type to store multiple skills, so instead of just assigning person['skills'] = {"name" : skill.name}; create an array and push the new skill object to it.
people.forEach(function(person){
skills.forEach(function(skill){
if(skill.personId == person.id){
//creates an array, if not yet created
person['skills'] = person['skills'] || [];
//push the skill object to the array
person['skills'].push(skill.name);
}
});
});
If you have 20 persons and 20 skills, then it will be 20 * 20 = 400 loops!
You can do it more efficiently using just 2 loops:
var skillsByPerson = {};
skills.forEach(function(skill) {
var personId = skill.personId;
var personSkills = skillsByPerson[personId] || (skillsByPerson[personId] = []);
personSkills.push({ name: skill.name });
});
people.forEach(function(person) {
person.skills = skillsByPerson[person.id] || [];
});
Here is the jsPerf test proof for performance check.
You're overwriting skills on each iteration (this part: person['skills'] = {"name" : skill.name};), instead you need to push a skill into an array of skills:
var people = [
{"id": 1, "name": "Tony Rogers",},
{"id": 2, "name": "Steven Grant",},
{"id": 3, "name": "Peter Wilson",}];
var skills = [{
"id": 1,
"name": "Engineering",
"personId": 1
}, {
"id": 2,
"name": "Painting",
"personId": 2
}, {
"id": 3,
"name": "Chemistry",
"personId": 3
}, {
"id": 4,
"name": "Physics",
"personId": 1
}, ]
people.forEach(function(person) {
person['skills'] = []; // create an empty skills array for each person
skills.forEach(function(skill) {
if (skill.personId == person.id) {
person['skills'].push({"name": skill.name}); // push the skill
}
});
});
console.log(people);