【问题标题】:How does one create a filter condition based on a configuration object for filtering data-items of an array?如何根据配置对象创建过滤条件以过滤数组的数据项?
【发布时间】:2020-12-23 18:25:49
【问题描述】:

我有一个动态的过程 - 根据复选框状态的变化 - 创建一种 config 对象,该对象描述了应该如何构建过滤数据项数组的条件。 p>

过滤器配置可能如下所示...

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' },
]

我希望条件匹配每个类别/类型(配置的键),但它的值可以是类别/类型数组中的任一个。 p>

根据提供的示例数据和规范,预期的过滤结果将是......

[{ 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

【问题讨论】:

  • 指定 "by all properties together" ...这是否意味着一个大的AND 链接条件,如publicationType === 'type-1' && publicationType === 'type-2' && termType === 'term-1' && termType === 'term-2' ... ?...因为这不起作用或者是每个类别/类型都匹配其值中的任何一个?
  • reportFormat: 'txt' 来自哪里?
  • 我添加了我的代码和沙箱,例如@evolutionxbox

标签: javascript arrays data-structures dynamic filter


【解决方案1】:

该方法的基本技术之一是利用这样一个事实,即几乎每个Array 方法都允许额外传递一个target 对象,该解决方案使用该对象与例如Array.prototype.filterArray.prototype.every

主要方法是为数据数组的filter 方法的每次迭代读取和应用过滤器配置

此函数需要迭代配置的entriesevery key-value(List) 对,以检查特定数据项是否与特定配置的条件条目匹配。

后一项任务由另一个函数完成,该函数可以访问数据项并“知道”两者,该数据项当前要检查 property-key 以及可能有效的属性值列表,这样可以很容易地检查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; }

【讨论】:

  • 嘿,我将您的解决方案添加到我的代码中,但过滤器返回一个空数组 codesandbox.io/s/checkbox-filter-vqex7?file=/src/App.js
  • @frontMaster ... 因为我自愿保持这个线程活着并且也很开心把你带到这里,所以我想继续解决这里的基本问题。向数据列表提供 (a) 配置的示例数据和一些更相关的项目,并指出代码确实失败的地方。我既没有代码沙盒帐户,也不想登录。顺便说一句,您需要将这两个功能直接提供到 App 模块的范围内; handleFilter 然后很容易被重写为const handleFilter = (config) => { setfilteredState(stat.filter(doesItemMatchConditionsOfBoundConfig, config)); };
  • @frontMaster ...此外,我想知道我是否正确理解了组合过滤条件的工作原理。
  • 我没有正确解释,我想制作一个带有复选框的过滤器以协同工作且独立。当所有过滤器属性都包含 data 时,您的解决方案工作正常。但是,如果其中一个过滤器属性为空,则它不起作用。现在我需要弄清楚让它工作。 @PeterSeliger
  • const filterConfig = { publicationType: ['type-1', 'type-2'], termType: ['term-1', 'term-2'], reportFormat: [], } 例如如果reportFormat属性空过滤器将返回一个空数组
猜你喜欢
  • 2020-05-25
  • 1970-01-01
  • 2018-10-04
  • 1970-01-01
  • 2019-09-15
  • 2021-04-10
  • 2021-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多