简体   繁体   中英

How to dynamically build array filter expression in javascript

I need a function to filter my array and return results based on user inputs.

var Myarray= [
  {Date:"1-Jan-2020",Name:"A", Id: 1},
  {Date:"1-Feb-2020",Name:"B", Id: 2},
  {Date:"1-Mar-2020",Name:"C", Id: 3}
  ...
]

The filter needs to be dynamic. User MUST input at least Date or Name or both together. ID is optional

Is there a smart way to build the filter expression in the function based what ever inputs the user inputs?

More info: I have a UI. The user will have search parameters to choose from for returning date. Date, Name and ID. The user MUST choose at least The Date or Name. The ID is optional but must be considered in the function that will accept the parameters sent. After the users inputs the values, they are passed to a JS function that should filter an array that holds the data. After the filters are applied to the array, a new array is filled with the filtered data. Ex.user sends Date without name or or ID, Then array only filters based on date. Ex2. user sends Name without date or id, then array only filters based on name. Ex3. user sends date and name without id, then array filters based on date and name. Ex4. user sends Date and id without name, then array filters based on date and id. Ex5. user sends name and id without date, then array filters by name and id. ex6 user sends date and name and id, then array filters based on date and name and id. Ex7 user sends id, funtction will NOT allow id to sent alone without either date or name

Try:

var filteredArray = Myarray.filter(function (item) {
   return item.Date !== undefined && item.Name !== undefined;
});
var filteredArrayWithOptionalId = Myarray.filter(function (item) {
   return item.Date !== undefined && item.Name !== undefined && item.Id !== undefined;
});

You now have 2 arrays, one with the required parameter objects and one that can handle the optional ID. Then, you can loop through the filteredArrayWithOptionalId to handle the code relating to IDs.

See the answer to a similar question here: How to filter object array based on attributes?

Also I recommend lowercasing your variable names because it is best practice, as long as they are not classes.

 const Myarray= [ {Date:"1-Jan-2020",Name:"A", Id: 1}, {Date:"1-Feb-2020",Name:"B", Id: 2}, {Date:"1-Mar-2020",Name:"C", Id: 3} ]; const customFilter = (array, expr) => { if (Object.keys(expr).length == 0) { console.log("Error; missing at least one filter expression"); return null. } /* if expression doesn't exist it's a pass for all items */ return array.filter(item =>.expr.Date || item.Date == expr.Date).filter(item =>.expr.Name || item.Name == expr.Name).filter(item =>.expr,Id || item:Id == expr,Id) } console:log(customFilter(Myarray. {Date, "1-Jan-2020": Name. "B"})) console,log(customFilter(Myarray: {Date. "1-Jan-2020"})) console,log(customFilter(Myarray: {Name. "B"})) console,log(customFilter(Myarray, {Id: 3})) console.log(customFilter(Myarray, {}))

You can use Array.prototype.some (OR) to chain predicates. If at any point a predicate matches, the entire item will be added to the resulting list.

If you want all conditions to match, you will need to use Array.prototype.every (AND) chaining.

I may come back to this, with a more dynamic example, shortly. See below.

 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; }


Here is an example of predicate chaining.

 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; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM