Reputation: 199
I'm trying to filter a list by tags:
const initialState = [
{id:1 ,name: 'Product A', image: 'pic-001.jpg', tags: ['nature', 'camping', 'outdoor']},
{id:2 ,name: 'Product B', image: 'pic-002.jpg', tags: ['winter', 'hiking', 'camping', 'snow']},
{id:3 ,name: 'Product C', image: 'pic-003.jpg', tags: ['vacation', 'family', 'kids', 'river', 'lake', 'fishing']}
]
I can filter the list by name using map
and filter
, my problem is when i try to list the products by tags. Do i have to use foreach
inside of my products filter? There's another way of doing it?
Upvotes: 12
Views: 29927
Reputation: 191936
You can create a Set of selected tags, and use Array#some
to check if at least one of the tags in the Set exists in the objects' tags list:
const initialState = [
{id:1 ,name: 'Product A', image: 'pic-001.jpg', tags: ['nature', 'camping', 'outdoor']},
{id:2 ,name: 'Product B', image: 'pic-002.jpg', tags: ['winter', 'hiking', 'camping', 'snow']},
{id:3 ,name: 'Product C', image: 'pic-003.jpg', tags: ['vacation', 'family', 'kids', 'river', 'lake', 'fishing']}
];
const filterByTags = ['nature', 'family'];
const filterByTagSet = new Set(filterByTags);
const result = initialState.filter((o) =>
o.tags.some((tag) => filterByTagSet.has(tag))
);
console.log(result);
Upvotes: 9
Reputation: 5940
Like that?
const filter = 'nature';
const filteredResult = initialState.filter((item) => {
return (item.tags.indexOf(filter) >= 0);
});
Upvotes: 16
Reputation: 149
Firstly to get all the tags and filter the duplicate tags from initialState. Save the array into uniqueTags.
Then compare the uniqueTags with initialState names, to create another array productTags with objects and its properties tags and products.
const initialState = [
{id:1 ,name: 'Product A', image: 'pic-001.jpg', tags: ['nature', 'camping', 'winter', 'outdoor']},
{id:2 ,name: 'Product B', image: 'pic-002.jpg', tags: ['winter', 'hiking', 'family', 'camping', 'snow']},
{id:3 ,name: 'Product C', image: 'pic-003.jpg', tags: ['vacation', 'family', 'kids', 'river', 'lake', 'fishing']}
]
let allTags = [];
initialState.map((t)=>t.tags).forEach((a)=>a.forEach((b)=>allTags.push(b)))
let uniqueTags = allTags.filter((a,i,arr)=>arr.indexOf(a,i+1)===-1)
productTags = [];
uniqueTags.forEach((u)=>{
initialState.forEach((t)=>{
if(t.tags.includes(u))
productTags.push({'tag': u, 'product':t.name});
})
})
console.log(JSON.stringify(productTags));
/*
[
{ "tag": "nature", "product": "Product A" },
{ "tag": "outdoor", "product": "Product A" },
{ "tag": "winter", "product": "Product A" },
{ "tag": "winter", "product": "Product B" },
{ "tag": "hiking", "product": "Product B" },
{ "tag": "camping", "product": "Product A" },
{ "tag": "camping", "product": "Product B" },
{ "tag": "snow", "product": "Product B" },
{ "tag": "vacation", "product": "Product C" },
{ "tag": "family", "product": "Product B" },
{ "tag": "family", "product": "Product C" },
{ "tag": "kids", "product": "Product C" },
{ "tag": "river", "product": "Product C" },
{ "tag": "lake", "product": "Product C" },
{ "tag": "fishing", "product": "Product C" }
] */
To form the correct object, I have changed the code to:
const initialState = [
{id:1 ,name: 'Product A', image: 'pic-001.jpg', tags: ['nature', 'camping', 'winter', 'outdoor']},
{id:2 ,name: 'Product B', image: 'pic-002.jpg', tags: ['winter', 'hiking', 'family', 'camping', 'snow']},
{id:3 ,name: 'Product C', image: 'pic-003.jpg', tags: ['vacation', 'family', 'kids', 'river', 'lake', 'fishing']}
]
let allTags = [];
initialState.map((t)=>t.tags).forEach((a)=>a.forEach((b)=>allTags.push(b)))
let uniqueTags = allTags.filter((a,i,arr)=>!arr.includes(a,i+1))
productTags = [];
uniqueTags.forEach((u)=>{
let productName = [];
initialState.forEach((t)=>{
if(t.tags.includes(u))
productName.push(t.name);
})
productTags.push({tag:u, products:productName});
})
console.log(JSON.stringify(productTags));
/*
productTags = [
{"tag":"nature","products":["Product A"]},
{"tag":"outdoor","products":["Product A"]},
{"tag":"winter","products":["Product A","Product B"]},
{"tag":"hiking","products":["Product B"]},
{"tag":"camping","products":["Product A","Product B"]},
{"tag":"snow","products":["Product B"]},
{"tag":"vacation","products":["Product C"]},
{"tag":"family","products":["Product B","Product C"]},
{"tag":"kids","products":["Product C"]},
{"tag":"river","products":["Product C"]},
{"tag":"lake","products":["Product C"]},
{"tag":"fishing","products":["Product C"]}
]
*/
Upvotes: 1
Reputation: 38
you can use indexOf function
var foo = initialState.filter(function(elm){
return elm.tags.indexOf("camping")>=0
});
Upvotes: 1