我试图创建一个接收两个参数的过滤函数:一个数组(将被过滤)和一个作为过滤标准的对象。
考虑如下数组结构:
const items = [
{
category: "Social",
areasAffected: ["Area_01", "Area_02"],
},
{
category: "Environmental",
areasAffected: ["Area_01", "Area_02", "Area_03", "Area_04"],
}
];
,考虑如下对象:
const filters = {
category: [{ value: "Social", label: "Social" }],
areasAffected: [{ value: "Area_01", label: "Area_01" }]
}
和我已经定义过滤器函数为:
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()
)
);
});
}
});
});
};
当我运行这个函数时,它返回一个空数组。有人有什么建议吗?
代码本身有两个问题。首先,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()
是多余的。