javascript - 如何根据配置对象创建过滤条件以过滤数组的数据项?
问题描述
我有一个动态的过程 - 根据复选框状态的变化 - 创建一种config
对象,该对象描述了应该如何构建过滤数据项数组的条件。
过滤器配置可能看起来像这样......
const filter = {
publicationType: ['type-1', 'type-2'],
termType: ['term-1', 'term-2'],
reportFormat: ['xml'],
}
一个简化的数据项列表看起来像这样......
const data = [
{ id: 1, reportFormat: 'txt', termType: 'term-1', publicationType: 'type-1' },
{ id: 2, reportFormat: 'xml', termType: 'term-2', publicationType: 'type-2' },
{ id: 3, reportFormat: 'txt', termType: 'term-2', publicationType: 'type-2' },
]
我希望条件匹配每个类别/类型(配置的键),但它的值可以是类别/类型数组中的一个。
根据提供的示例数据和规范,预期的过滤结果将是......
[{ id: 2, reportFormat: 'xml', termType: 'term-2', publicationType: 'type-2' }]
filter
一种基于提供的配置对象构建正确过滤条件的方法看起来如何。
下面是我尝试制作过滤器功能但过滤仅在单个 Select 组件上正常工作,如果我尝试过滤多个 Select 组件 - 数据重复。
const handleFilter = (val) => {
const filterKeys = Object.keys(val);
const filteredStats = [];
// loop objects in fetched arr
for (const item of stat) {
// loop properties by which filtering data
filterKeys.forEach((keys) => {
// check if data property match with a filtering property in array
const isPresent = val[keys].some((key) => {
const statProperty = item[keys];
const filterProperty = key;
return filterProperty === statProperty;
});
if (isPresent) {
filteredStats.push(item);
}
});
}
setfilteredState(filteredStats);
};
https://codesandbox.io/s/checkbox-filter-vqex7?file=/src/App.js
解决方案
该方法的基本技术之一是利用这样一个事实,即几乎每种Array
方法都允许额外传递的target
对象,该解决方案与例如Array.prototype.filter
和 Array.prototype.every
主要方法是为数据数组方法的每次迭代读取和应用过滤器配置filter
。
此函数需要迭代配置的every
键值(列表)对,entries
以检查特定数据项是否与特定配置的条件条目匹配。
后一项任务由另一个函数完成,该函数可以访问数据项并且“知道”两者,该数据项当前要检查属性键和可能有效的属性值列表,这使得检查变得容易最终条件是否some
适用。
还有一个边缘情况,空值列表,需要由后一个函数处理。由于其检查的真实性依赖于some
...(并且some
空数组的默认返回值是false
... )...必须通过显式返回其满足的前提条件来[].some(x => true) === false
单独处理这种情况。true
valueList.length === 0
function doesBoundItemMatchConditionEntry([key, valueList]) {
const item = this;
const itemValue = item[key];
return ((
valueList.length === 0
) || (
item.hasOwnProperty(key) &&
valueList.some(value => value === itemValue)
));
}
function doesItemMatchConditionsOfBoundConfig(item) {
// const config = this;
return Object
.entries(this)
.every(doesBoundItemMatchConditionEntry, item);
}
const filterConfig = {
publicationType: ['type-1', 'type-2'],
termType: ['term-1', 'term-2'],
reportFormat: ['xml'],
}
const sampleData = [
{ id: 1, reportFormat: 'txt', termType: 'term-1', publicationType: 'type-1' },
{ id: 2, reportFormat: 'xml', termType: 'term-2', publicationType: 'type-2' },
{ id: 3, reportFormat: 'txt', termType: 'term-2', publicationType: 'type-2' },
{ id: 4, reportFormat: 'txt', termType: 'term-2', publicationType: 'type-1' },
{ id: 5, reportFormat: 'xml', termType: 'term-1', publicationType: 'type-2' },
{ id: 6, reportFormat: 'txt', termType: 'term-1', publicationType: 'type-2' },
]
console.log(
'sampleData.filter(doesItemMatchConditionsOfBoundConfig, filterConfig) ...',
sampleData.filter(doesItemMatchConditionsOfBoundConfig, filterConfig)
);
console.log(
`sampleData.filter(doesItemMatchConditionsOfBoundConfig, {
publicationType: ['type-2'],
termType: ['term-1'],
reportFormat: [],
}) ...`,
sampleData.filter(doesItemMatchConditionsOfBoundConfig, {
publicationType: ['type-2'],
termType: ['term-1'],
reportFormat: [],
})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
推荐阅读
- html - Firefox 和 Chrome 的不同边距大小
- angular - UglifyJSPlugin 在构建时出现内存不足错误
- three.js - Three.js:在透明材质上投射阴影
- php - 反向名称的 SQL Like 查询返回结果
- apache-spark - Spark Streaming:多个 Kerberos 身份验证
- svg - 根据数据集,圆圈未显示在 svg 上
- java - DOM W3c XML 元素解析空属性
- javassist - 如何定义一个新方法并拦截和委托对该方法的调用?
- mysql - mysql中的有线子查询
- python-3.x - 如何在 Mac 上安装 python pdal?