当有多个值时,如何使我的过滤器作为 "and" 而不是 "or" 工作?

How can I make my filter work as an "and" instead of "or" when there are multiple values?

我的过滤器有两个限制。

1:当有多个值时,它作为 'or' 而不是 'and'。

例如

filterArr = {'claim_number': null, 'status': 'Approved', 'patient': 'John Connor', 'service_date': null}

this.rows = [ 
   { 'claim_number': 1234, 'status': 'Approved', 'patient': 'John Connor', 'service_date': '1/10/2018', etc ...}
   { 'claim_number': 4567, 'status': 'Approved', 'patient': 'James Brown', 'service_date': '3/11/2018', etc ...}
   { 'claim_number': 7890, 'status': 'Approved', 'patient': 'Steven Hawkins', 'service_date': '2/1/2018', etc ...}

目前所有这些项目都会匹配,而只有第一个应该匹配,因为只有第一个同时具有 "status: Approved" 和 "patient: John Connor."

2:第二个限制是我想在 this.rows.

中有部分字符串与完整字符串匹配时触发匹配

例如

filterArr = {'claim_number': 12, 'status': 'Approved', 'patient': null, 'service_date': null}

this.rows = [ 
    { 'claim_number': 1234, 'status': 'Approved', 'patient': 'John 
       Connor', 'service_date': '1/10/2018', etc ...}
    { 'claim_number': 4567, 'status': 'Approved', 'patient': 'James 
       Brown', 'service_date': '3/11/2018', etc ...}
    { 'claim_number': 7890, 'status': 'Approved', 'patient': 'Steven Hawkins', 'service_date': '2/1/2018', etc ...}

同样只有第一个应该匹配,因为它包含正确的 "status" 和 "claim_number."

中的前两位数字

这应该相对简单,因为我在传递特定密钥时它可以正常工作,但现在过滤器是动态的,它似乎无法正常工作。

我附上了一个 jsFiddle 以供参考,但它没有正确执行,因为我在 Angular 项目中使用 Reactive Forms。此外,请仅包含使用 ES5 或 ES6 解决的答案。我不能使用 flatMap() 和其他实验性功能。谢谢你。

看看这是否适合你:

const rows = [ { 'claim_number': '1234', 'status': 'Approved', 'patient': 'John Connor', 'service_date': '1/10/2018'}, { 'claim_number': '4567', 'status': 'Approved', 'patient': 'James Brown', 'service_date': '3/11/2018'}, { 'claim_number': '7890', 'status': 'Approved', 'patient': 'Steven Hawkins', 'service_date': '2/1/2018'} ]

const filtrate = (i, f) => {
  const vals = Object.values(f).reduce((r,c) => (!!c ? r.push(c) : 0, r), [])
  return vals.every(x => Object.values(i).some(y => y.includes(x)))
}
const filterBy = (arr, f) => arr.filter(x => filtrate(x, f))

console.log(filterBy(rows, {'claim_number': null, 'status': 'Approved', 'patient': 'John Connor', 'service_date': null}))
console.log(filterBy(rows, {'claim_number': '12', 'status': 'Approved', 'patient': null, 'service_date': null}))

想法是首先 clean/sanitize 过滤器对象,一旦您只有干净的值,然后通过 Array.every & Array.some & Array.includes 实际进行整个搜索。

另请注意,我将数字转换为字符串,因为如果您要搜索 12 是否属于 1234 等,这似乎是您的意图。

为清楚起见,将相同的代码展开:

const rows = [ { 'claim_number': '1234', 'status': 'Approved', 'patient': 'John Connor', 'service_date': '1/10/2018'}, { 'claim_number': '4567', 'status': 'Approved', 'patient': 'James Brown', 'service_date': '3/11/2018'}, { 'claim_number': '7890', 'status': 'Approved', 'patient': 'Steven Hawkins', 'service_date': '2/1/2018'} ]

const filtrate = (item, filter) => {
  const values = Object.values(filter).reduce((accumulator, current) => {
  if(!!current)
    accumulator.push(current) 
    return accumulator
  }, [])
  return values.every(value => {
    return Object.values(item).some(itm => itm.includes(value))
  })
}
const filterBy = (allRows, filterObject) => {
  return allRows.filter(row => filtrate(row, filterObject))
}

console.log(filterBy(rows, {'claim_number': null, 'status': 'Approved', 'patient': 'John Connor', 'service_date': null}))
console.log(filterBy(rows, {'claim_number': '12', 'status': 'Approved', 'patient': null, 'service_date': null}))

这是我最终使用的答案。我发现它是最直接的。

@Input() filters: Array<any>;
allRows: Array<any> = [];

applyFilters() {
    this.rows = this.allRows;

    this.rows = this.rows.filter(row => {
        for (let filter of this.filters) {
            const filterVal = this.filtersForm.get(filter.key).value;
            const rowVal = row[filter.key];

            if (!!filterVal && rowVal.toString().toLowerCase().includes(filterVal.toString().toLowerCase())) {
                return true;
            }
        }

        return false;
    })
}