Вы можете использовать Array.prototype.some
(ИЛИ) для цепочки предикатов. Если в какой-то момент предикат совпадает, весь элемент будет добавлен в итоговый список.
Если вы хотите, чтобы все условия соответствовали, вам нужно использовать Array.prototype.every
(AND).
Я могу вернуться к этому, с более динамичным примером c, в ближайшее время. См. Ниже.
const main = () => {
let arr = [
{ Date: "1-Jan-2020" , Name: "A" , Id: 1 }, // Yes
{ Date: "1-Feb-2020" , Name: "B" , Id: 2 }, // Yes
{ Date: "1-Mar-2020" , Name: null , Id: 3 }, // Yes
{ Date: null , Name: null , Id: 4 } // No
]
console.log(filterWithPredicates(arr, predicates))
}
const predicates = {
date: (record) => record.Date != null,
name: (record) => record.Name != null
};
const filterWithPredicates = (list, predicates) => {
return list.filter(item => {
return Object.values(predicates).some(predicate => {
if (predicate(item)) { return true }
})
return false
})
}
main()
.as-console-wrapper { top: 0; max-height: 100% !important; }
Вот пример цепочки предикатов.
const Predicates = {
date: (record) => record.Date != null,
name: (record) => record.Name != null
}
const main = () => {
let arr = [
{ Date: "1-Jan-2020" , Name: "A" , Id: 1 }, // Yes
{ Date: "1-Feb-2020" , Name: "B" , Id: 2 }, // Yes
{ Date: "1-Mar-2020" , Name: null , Id: 3 }, // Yes
{ Date: null , Name: null , Id: 4 } // No
]
let filter = new Filter().chain().or(Predicates.date).or(Predicates.name)
console.log(filter.execute(arr))
}
class Filter {
constructor() {
this.filters = []
}
chain() {
this.filters = []
return this
}
or(predicate) {
this.filters.push({ fn : predicate, op : 'or' })
return this
}
and(predicate) {
this.filters.push({ fn : predicate, op : 'and' })
return this
}
execute(items) {
return items.reduce((results, item) =>
this.__shouldKeepItem(item) ? results.concat(item) : results, [])
}
/** @private */
__startCondition() {
return this.filters.length ? this.filters[0].op === 'and' ? 1 : 0 : 0
}
/** @private */
__shouldKeepItem(item) {
return this.filters.reduce((keep, filter) => {
switch (filter.op) {
case 'or' : return keep || filter.fn(item)
case 'and' : return keep && filter.fn(item)
default : return keep
}
}, this.__startCondition())
}
}
main()
.as-console-wrapper { top: 0; max-height: 100% !important; }