I'd like to filter an array of objects. The array is a list of sport classes, and the objects are the classes.
It looks like this :
const list = [{category: "yoga", level: "beginner", duration: "15 minutes"}]
I have to apply filter so the user can choose between category (yoga, pilates...) level (beginner, advanced..).
I need to find the intersection of the filter, meaning if "yoga" and "beginner" are selected, I'd like to return only beginner yoga classes.
User can turn true/false the variables beginnnerFilter etc.. and the variables cardio/yoga etc... So if the yoga filter is true, yogaFilter = "yoga". If false, yogaFilter = ""
Example:
function filterIntersect() {
let filteredListCategory = [];
let filteredListLevel = [];
for(let i = 0; i < list.length; i ) {
if (list[i].category.toLowerCase() === cardio) {
filteredListCategory.push(list[i])
} else if (list[i].category.toLowerCase() === yoga) {
filteredListCategory.push(list[i])
} else if (list[i].category.toLowerCase() === boxing) {
filteredListCategory.push(list[i])
} else if (list[i].category.toLowerCase() === dance) {
filteredListCategory.push(list[i])
} else if (list[i].category.toLowerCase() === pilates) {
filteredListCategory.push(list[i])
} else if (list[i].category.toLowerCase() === stretching) {
filteredListCategory.push(list[i])
}
}
if (allFilterCategory === true) {
filteredListCategory = [...list];
}
for(let k = 0; k < list.length; k ) {
if (list[k].level.toLowerCase() === beginnerFilter) {
filteredListLevel.push(list[k])
} else if (list[k].level.toLowerCase() === intermediateFilter) {
filteredListLevel.push(list[k])
} else if (list[k].level.toLowerCase() === advancedFilter) {
filteredListLevel.push(list[k])
}
}
if (allFilterLevel === true) {
filteredListLevel = [...list];
}
let finalList = filteredListCategory.filter(item=> filteredListLevel.includes(item));
return finalList.length === 0 ? list : finalList;
}
I manage to return a filtered array but it doesn't work as expected. Sometimes the filters do not apply and I have the full list instead of the filtered list. I'm not sure the for loop is appropriate here? I also tried using new Set but was not working either. Big thanks.
CodePudding user response:
You can use the .filter
and .some
method of arrays instead of if
-statements and for
-loops. E.g.
const categoryChoices = [
{ category: "yoga", checked: false },
{ category: "meditation", checked: true },
{ category: "pilates", checked: false },
{ category: "cardio", checked: true },
];
const levelsChoices = [
{ level: "beginner", checked: true },
{ level: "intermediate", checked: true },
{ level: "advanced", checked: false },
];
const data = [
{ category: "yoga", level: "beginner", duration: '30 minutes' },
{ category: "yoga", level: "intermediate", duration: '60 minutes' },
{ category: "yoga", level: "advanced", duration: '90 minutes' },
{ category: "meditation", level: "beginner", duration: '30 minutes' },
{ category: "meditation", level: "intermediate", duration: '60 minutes' },
{ category: "meditation", level: "advanced", duration: '90 minutes' },
{ category: "pilates", level: "beginner", duration: '30 minutes' },
{ category: "pilates", level: "intermediate", duration: '60 minutes' },
{ category: "pilates", level: "advanced", duration: '90 minutes' },
{ category: "cardio", level: "beginner", duration: '30 minutes' },
{ category: "cardio", level: "intermediate", duration: '60 minutes' },
{ category: "cardio", level: "advanced", duration: '90 minutes' },
];
const checkedCategories = categoryChoices
.filter((c) => c.checked)
.map((c) => c.category);
const checkedLevels = levelsChoices
.filter((l) => l.checked)
.map((l) => l.level);
const filteredData = data.filter(
({ category, level }) =>
checkedCategories.some((c) => c === category) &&
checkedLevels.some((l) => l === level)
);
console.log(filteredData);