Dynamically filtering an array of objects in JavaScript

I recently needed a way to filter an array of objects based on user input. The end-user experience would be similar to how filtering works in Excel (a column drop down filter where the user can select multiple values across multiple columns).

At first, it made sense to use Array.prototype.filter() to accomplish this, however that would require me to know the properties to filter by and the values to filter for. This wouldn't work since the properties (the field columns) and filter values would be controlled by the end-user.

To address this challenge, I wrote a helper function that filters an array of objects based on filter criteria. This allows for dynamic filtering with n filter criteria. This function, at the moment, checks for exact matches. So "green" wouldn't match "Green" and "4" wouldn't match 4. Future enhancements would be to include other operators and case-insensitive matching.

Array.prototype.flexFilter = function(info) {
  
  // Set our variables
  var matchesFilter, matches = [], count = 0;
  
  /***********
   Helper function to loop through the filter criteria to find 
   matching values.
   Each filter criteria is treated as "AND". So each item must 
   match all the filter criteria to be considered a match.
   Multiple filter values in a filter field are treated as "OR"
   i.e. ["Blue", "Green"] will yield items matching a value 
   of Blue OR Green.
  ************/
  matchesFilter = function(item) {
    for (var n = 0; n < info.length; n++) {
      if (info[n]["Values"].indexOf(item[info[n]["Field"]]) > -1) {
        count++;
      }
    }
    // If TRUE, then the current item in the array meets 
    // all the filter criteria
    return count == info.length;
  }

  // Loop through each item in the array
  for (var i = 0; i < this.length; i++) {

    // Determine if the current item matches the filter criteria
    if (matchesFilter(this[i])) {
      matches.push(this[i]);
    }

  }

  // Give us a new array containing the objects matching the filter criteria
  return matches;
}

Usage

var data = [
  { ID: 1, Name: "John", Color: "Blue", Location: "Up" },
  { ID: 2, Name: "Pauline", Color: "Green", Location: "Up" },
  { ID: 3, Name: "Ahmed", Color: "Orange", Location: "Left" },
  { ID: 4, Name: "Diego", Color: "Pink", Location: "Up" },
  { ID: 5, Name: "Maria", Color: "Black", Location: "Down" },
  { ID: 6, Name: "Gus", Color: "Green", Location: "Up" },
  { ID: 7, Name: "Brian", Color: "Pink", Location: "Left" },
  { ID: 8, Name: "Shelley", Color: "Green", Location: "Right" },
  { ID: 9, Name: "Leonardo", Color: "Blue", Location: "Right" },
  { ID: 10, Name: "Big Daddy", Color: "Green", Location: "Down" }
];

var criteria = [
  { Field: "Color", Values: ["Green"] },
  { Field: "Location", Values: ["Up", "Down"] }
];
var filtered = data.flexFilter(criteria);
console.log(filtered);
 
  

Here it is on GitHub: https://github.com/halshing/General/tree/master/ArrayOfObjectsFilter


Along with my other comment I wanted to thank you for getting me started in the right direction. I was trying to figure out how to do this but couldn't for the life of me think of how. Again thanks!

You could simplify the implementation as: Array.prototype.flexFilter = function(info) {     return this.filter(item => {         return info.every(i => {             return i.Values.indexOf(item[i.Field]) > -1;         });     }); }

var criteria = [ { Field: "Color", Values: ["Green"] }, { Field: "Location", Values: ["Up", "Down"] } ]; Data is filtering with AND operator between two criteria. If we want filter with OR operator,how to implement?

Like
Reply

To view or add a comment, sign in

More articles by Hasan S.

Others also viewed

Explore content categories