39

I'm playing around with arrays trying to understand them more since I tend to work with them alot lately. I got this case where I want to search an array and compare it's element values to another array which contains values of some selected filters.

For example if I select 3 filters, I want later to write matches in new array - only those which match all 3 filters.

For easier understanding I set up an example on http://jsfiddle.net/easwee/x8U4v/36/

Code is:

var workItems =   [
    { "id": 2616, "category": ".category-copy .category-beauty .category-fashion"}, //this is a match
    { "id": 1505, "category": ".category-beauty"}, // NOT
    { "id": 1500, "category": ".category-beauty .category-fashion"}, // NOT
    { "id": 692, "category": ".category-stills .category-retouching"}, // NOT
    { "id": 593, "category": ".category-beauty .category-capture .category-fashion .category-product .category-stills .category-stills-retouching "}, // NOT
    { "id": 636, "category": ".category-beauty .category-copy .category-fashion"}, //this is a match
    { "id": 547, "category": ".category-fashion .category-lifestyle .category-stills .category-stills-retouching "}, // NOT
    { "id": 588, "category": ".category-capture .category-recent-work .category-copy .category-beauty .category-fashion"} //this is a match
];

var filtersArray = [".category-beauty", ".category-fashion", ".category-copy"];

var i;
for (i = 0; i < filtersArray.length; ++i) {
    var searchString = filtersArray[i];
    console.log('Searching for: ' + searchString);
    var filtered = $(workItems).filter(function(){
        return this.category.indexOf(searchString);
    });    
}   
console.log('Filtered results: ' + JSON.stringify(filtered, null, 4));

I also tried with

filtered = $.grep(workItems, function(element, index){
    return element.category.indexOf(filtersArray[i]); 
}, true);

but it matches only the first filter and only if it's at the begining of workItems.category

I've tried many different solutions but can't really make this work. What function should I use to return the desired result?

0

4 Answers 4

24

You can use .filter() method of the Array object:

var filtered = workItems.filter(function(element) {
   // Create an array using `.split()` method
   var cats = element.category.split(' ');

   // Filter the returned array based on specified filters
   // If the length of the returned filtered array is equal to
   // length of the filters array the element should be returned  
   return cats.filter(function(cat) {
       return filtersArray.indexOf(cat) > -1;
   }).length === filtersArray.length;
});

http://jsfiddle.net/6RBnB/

Some old browsers like IE8 doesn't support .filter() method of the Array object, if you are using jQuery you can use .filter() method of jQuery object.

jQuery version:

var filtered = $(workItems).filter(function(i, element) {
   var cats = element.category.split(' ');

    return $(cats).filter(function(_, cat) {
       return $.inArray(cat, filtersArray) > -1;
    }).length === filtersArray.length;
});
Sign up to request clarification or add additional context in comments.

5 Comments

Array.prototype.filter needs ECMAScript 5 support and only is available on modern browsers, i think for these basic works our own written functions is better, Aside from this, it's a cross-browser solution
Cool, the last line could be simplified using Array.prototype.every. Like this: return filtersArray.every(function(cat) { return ~cats.indexOf(cat); })
I'm using jQuery - so I guess this solution will work. Atleast it matched any tests I sent in and IE8 is not really a problem in this case since this is mostly practice work. Thanks a lot for help!
@ABFORCE Well, if you really care about cross-browser issues, you should know that IE8 doesn't support indexOf method of array object, the only browser that makes problem is IE, most previous versions of other browsers support most of the ECMAScript 5 methods, even Firefox v1, btw your answer doesn't solve the issue.
Amazing way to filter multiple arrays for multiple values! Exactly what I needed -- thanks!
18

You can use .filter() with boolean operators ie &&:

     var find = my_array.filter(function(result) {
       return result.param1 === "srting1" && result.param2 === 'string2';
     });
     
     return find[0];

Comments

6

The best way would be to have an array of values to search and then loop the data.

const ids = [1,2,3];
const products = DATA.filter((item) => ids?.includes(item.id));

2 Comments

I'd not seen ?.includes() before, very elegant.
@TopMarx typescript sorry hehe
0

this trick will help if anyone want to apply filter on the base of more than of property of object.

searchCustomers(){
        let tempCustomers = this.customers
        if (this.searchValue != '' && this.searchValue) {
        
        tempCustomers = tempCustomers.filter((item) => {
          

          return item.name
            .toUpperCase()
            .includes(this.searchValue.toUpperCase()) || item.customer_no
            .toUpperCase()
            .includes(this.searchValue.toUpperCase()) || item.mobno
            .toUpperCase()
            .includes(this.searchValue.toUpperCase()) 
        })
      }
      return tempCustomers;
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.