简体   繁体   中英

filter an array of objects by an array attribute with another array

The following code does NOT return the expected results of an array with 1 item. Can someone please enlighten me about the correct syntax?

 let things = [{ Name: 'Bill', Tags: ['tall', 'dude'] }, { Name: 'Ted', Tags: ['short', 'dude'] } ]; let selectedTags = ['short', 'chick']; let filtered = things.filter((thing => thing.Tags.indexOf(selectedTags) >= 0)); console.log(filtered); 

You are passing Array selectedTags to includes . You need to check loop through selectedTags and check if tag is present in .Tags of object.

 let things = [{Name: 'Bill', Tags: ['tall','dude']}, {Name: 'Ted', Tags: ['short','dude']}]; console.log(things); let selectedTags = ['short','chick']; let filtered = things.filter(x => { for(let tag of selectedTags){ if(x.Tags.includes(tag)) return true; } return false; }); console.log(filtered); 

selectedTags is an array.

.indexOf() is wainting for a string.

You can get the string into your array by selected with index, like :

thing.Tags.indexOf(selectedTags[0])

So it looks like you want to filter things based on if any of thing.Tags is in selectedTags .

You would do something like this

things.filter(thing => thing.Tags.some(tag => selectedTags.includes(tag)));

This is, I think, the most expressive way to write it. Give me all things where some of thing.Tags are included in the selectedTags array.

If you need to filter the items that have some tag that is present on the selectedTags array, then you can go with this:

 let things = [ {Name: 'Bill', Tags: ['tall', 'dude']}, {Name: 'Ted', Tags: ['short', 'dude']} ]; let selectedTags = ['short', 'chick']; let filtered = things.filter( thing => selectedTags.some(x => thing.Tags.includes(x)) ); console.log(filtered); 
 .as-console {background-color:black !important; color:lime;} .as-console-wrapper {max-height:100% !important; top:0;} 

If you need to filter the items that have all the tags present on the selectedTags array, then you can use:

 let things = [ {Name: 'Bill', Tags: ['tall', 'dude']}, {Name: 'Ted', Tags: ['short', 'dude']}, {Name: 'Test', Tags: ['short', 'chick']} ]; let selectedTags = ['short', 'chick']; let filtered = things.filter( thing => selectedTags.every(x => thing.Tags.includes(x)) ); console.log(filtered); 
 .as-console {background-color:black !important; color:lime;} .as-console-wrapper {max-height:100% !important; top:0;} 

You have to iterate over each things element and analyze every item in its Tags attribute array:

 let things = [{ Name: 'Bill', Tags: ['tall', 'dude'] }, { Name: 'Ted', Tags: ['short', 'dude'] } ]; let selectedTags = ['short', 'chick']; let filtered = things.filter(el => { //Use reduce on to get a count of how many matching tags return el.Tags.reduce((accum, tag) => { if (selectedTags.indexOf(tag) > -1) { accum += 1; } return accum; }, 0); }); console.log(filtered); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM