javascript - filter an array of objects based on an object with an array as it's property value in react
问题描述
I'm trying to create a filter function that receives two arguments: an array (which is going to be filtered) and an object which is the filter criteria.
Consider the array structure as:
const items = [
{
category: "Social",
areasAffected: ["Area_01", "Area_02"],
},
{
category: "Environmental",
areasAffected: ["Area_01", "Area_02", "Area_03", "Area_04"],
}
];
and, consider the object as below:
const filters = {
category: [{ value: "Social", label: "Social" }],
areasAffected: [{ value: "Area_01", label: "Area_01" }]
}
and I have defined the filter function as:
const filterChallenges = (items, filters) => {
const filterKeys = Object.keys(filters);
return items.filter((item) => {
filterKeys.forEach((key) => {
if (!Array.isArray(item[key])) {
return item[key]
.toString()
.toLowerCase()
.includes(
filters[key].map((filterEle) =>
filterEle.value.toString().toLowerCase()
)
);
} else {
return item[key].map((arrEle) => {
arrEle
.toString()
.toLowerCase()
.includes(
filters[key].map((filterEle) =>
filterEle.value.toString().toLowerCase()
)
);
});
}
});
});
};
when I run the function, it returns an empty array. Does anybody have any suggestion?
解决方案
代码本身有两个问题。首先,forEach
不返回值。Array.every()
如果您想要求所有过滤器都匹配,您将需要在此处使用。否则你会想要使用Array.some()
.
其次,String.includes()
不采用数组,而是采用字符串。在这里,Array.every()
如果您希望过滤器数组的所有项目都匹配该值,则需要再次使用,否则使用Array.some()
. 至于else
处理作为数组的项值的分支,Array.some()
如果您只希望其中一个数组值匹配,则需要使用。
const items = [
{
category: "Social",
areasAffected: ["Area_01", "Area_02"],
},
{
category: "Environmental",
areasAffected: ["Area_01", "Area_02", "Area_03", "Area_04"],
},
];
const filterChallenges = (items, filters) => {
const filterKeys = Object.keys(filters);
return items.filter((item) => {
// ALL of the filters must be matched (.every())
return filterKeys.every((filterKey) => {
if (!Array.isArray(item[filterKey])) {
const candidateValue = item[filterKey].toString().toLowerCase();
// ALL of the filter values must be included in the item value
// (.every())
return filters[filterKey].every((filterEle) =>
candidateValue.includes(filterEle.value.toString().toLowerCase())
);
}
// Value is an array, ONE element (.some()) must match ALL of the
// filter values (.every())
return item[filterKey].some((candidate) => {
const candidateValue = candidate.toString().toLowerCase();
return filters[filterKey].every((filterEle) =>
candidateValue.includes(filterEle.value.toString().toLowerCase())
);
});
});
});
};
const ret = filterChallenges(items, {
category: [{ value: "Social", label: "Social" }],
areasAffected: [{ value: "Area_01", label: "Area_01" }],
});
console.log(ret);
此外,如果您的所有值都是字符串,那么.toString()
是多余的。
推荐阅读
- javascript - 从列出/关联经过身份验证的用户的 MongoDB 文档中获取对象
- java - 如何将普通pdf转换为小册子pdf,反之亦然
- sqlite - 使用 SchemaSpy 为本地 sqlite 数据库生成架构时出现连接失败警告
- c# - 在 C# 中对列表中的每个输入执行计算
- javascript - 数组返回长度为 0,尽管它有值
- node.js - 为什么将请求正文内容设为空?
- hyperledger-fabric - 在 IBM Blockchain Platform Visual Studio Extension 上打包智能合约时出错
- python - Python:从更大的列表中填充列表的空列表
- java - java中的包 - 必要吗?
- mysql - MYSQL如何排除2个不同日期之间的工作日