Reputation: 217
I am attempting to filter some events and their corresponding time slots. The data structure is like so:
var items = [
{
title: 'Category Title',
events: [
{
title : '1:00pm',
category : 1
},
{
title: '2:00pm',
category : 2
}
]
},
{
title: 'Category Title 2',
events: [
{
title : '3:00pm',
category : 1
},
{
title: '4:00pm',
category : 2
}
]
}
];
I am wanting to filter events by their category. I've tried using filters/maps but can't seem to figure it out. For example, how would I filter the list to only return items with the category of 1?
Upvotes: 2
Views: 6772
Reputation: 33726
You can use the function filter
along with the function some
to get those items with a specific category within the array events
.
This example has an item which events array contains a category === 3
var items = [ { title: 'Category Title', events: [ { title : '1:00pm', category : 1 }, { title: '2:00pm', category : 2 } ] }, { title: 'Category Title 2', events: [ { title : '3:00pm', category : 1 }, { title: '4:00pm', category : 2 } ] }, { title: 'Category Title 3', events: [ { title : '3:00pm', category : 1 }, { title: '4:00pm', category : 3 } ] }],
cat = 3,
result = items.filter(o => o.events.some(({category}) => cat === category));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you need to get only the events with category === 3
use the function reduce
:
var items = [ { title: 'Category Title', events: [ { title : '1:00pm', category : 1 }, { title: '2:00pm', category : 2 } ] }, { title: 'Category Title 2', events: [ { title : '3:00pm', category : 1 }, { title: '4:00pm', category : 2 } ] }, { title: 'Category Title 3', events: [ { title : '3:00pm', category : 1 }, { title: '4:00pm', category : 3 } ] }],
cat = 3,
result = items.reduce((a/*Accumulator*/, o/*Current object in array*/) => {
// 1. We get the events with a specific category (In this case -> 3)
var filtered = o.events.filter(({category}) => cat === category);
// 2. If the previous filter returns at least one event, we need to push
// the current object 'o' with the filtered events.
if (filtered.length) { // if length !== 0 we need to push the object.
// 3. We use Object.assign to avoid any mutation over the original object.
// So, basically we create a new object with the original properties
// and finally we assign the filtered events to the property events.
a.push(Object.assign({}, o, {events: filtered}));
}
return a;
}, []/*Initial value (this array will contain the filtered objects)*/);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 3452
you can use filter to get the reduced list but you can do this in other ways like reduce.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
var items = [ { title: 'Category Title', events: [ { title : '1:00pm', category : 1 }, { title: '2:00pm', category : 2 } ] }, { title: 'Category Title 2', events: [ { title : '3:00pm', category : 1 }, { title: '4:00pm', category : 2 } ] } ]; let cat1, cat2; items.forEach(item => { cat1 = item.events.filter(item => item.category === 1) cat2 = item.events.filter(item => item.category === 2) }) console.log(cat1, cat2)
Heres a bit more advanced you can give the function an array of categories you want and it will return an object with keys of all the categories and the events inside them. Hope this helps.
var items = [
{
title: 'Category Title',
events: [
{
title : '1:00pm',
category : 1
},
{
title: '2:00pm',
category : 2
}
]
},
{
title: 'Category Title 2',
events: [
{
title : '3:00pm',
category : 1
},
{
title: '4:00pm',
category : 2
}
]
}
];
function filter(cat, arr) {
return arr.filter(i => i.category === cat);
}
function getCategorys(category) {
return items.reduce((prev, curr) => {
category.forEach(cat => {
!prev[cat] ? prev[cat] = [] : null;
prev[cat] = [...filter(cat, curr.events), ...prev[cat]];
})
return prev;
}, {})
}
console.log(getCategorys([1,2]))
Upvotes: 1
Reputation: 32145
What you should do here is to use Array.filter()
method to filter your items
array, based on the sub events
array, which you can test upon with Array.some()
to find those with category===1
.
var filteredResults = items.filter(function(item) {
return item.events.some(e => e.category === 1);
});
Demo:
var items = [{
title: 'Category Title',
events: [{
title: '1:00pm',
category: 1
},
{
title: '2:00pm',
category: 2
}
]
},
{
title: 'Category Title 2',
events: [{
title: '3:00pm',
category: 1
},
{
title: '4:00pm',
category: 2
}
]
}
];
var result = items.filter(function(item) {
return item.events.some(e => e.category === 1);
});
console.log(result);
Upvotes: 1
Reputation: 7593
function hasCategory(item, cat) {
for(e in item.events){
if(item.events[e].category === cat) {
return true;
break;
}
}
return false;
}
var filtered = items.filter((item) => {
return hasCategory(item, 2);
});
console.log(filtered);
Upvotes: -1
Reputation: 157
You can use the following functions to get desired result:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
function filterByCategory(items, category) {
return items.reduce((events, i) => {
const filteredEvents = i.events.filter(e => e.category === category);
if (filteredEvents) {
return events.concat(filteredEvents);
}
return events;
}, []);
}
Upvotes: 0