Filtering array of objects by searching nested object properties

10,965

Solution 1

You could use Array#filter with looking into the nested arrays by using Array#some.

If the tag is found in a nested array, then iteration stops and the result is given back to the filter callback.

var array = [{ category: 'Business', users: [{ name: 'Sally', tags: [{ tag: 'accounting' }, { tag: 'marketing' }] }, { name: 'Bob', tags: [{ tag: 'sales' }, { tag: 'accounting' }] }] }, { category: 'Heritage', users: [{ name: 'Linda', tags: [{ tag: 'Italy' }, { tag: 'Macedonia' }] }, { name: 'George', tags: [{ tag: 'South Africa' }, { tag: 'Chile' }] }] }],
    tag = 'marketing',
    result = array.filter(a => a.users.some(u => u.tags.some(t => t.tag.includes(tag))));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Solution 2

The solution using Array.prototype.some() function:

var arr = [{ category: 'Business', users: [{ name: 'Sally', tags: [{ tag: 'accounting' }, { tag: 'marketing' }] }, { name: 'Bob', tags: [{ tag: 'sales' }, { tag: 'accounting' }] }] }, { category: 'Heritage', users: [{ name: 'Linda', tags: [{ tag: 'Italy' }, { tag: 'Macedonia' }] }, { name: 'George', tags: [{ tag: 'South Africa' }, { tag: 'Chile' }] }] }], 
    search_key = 'market',
    result = [];
    
arr.forEach(function(o){
    if (o.users.some(function(v){
        return v.tags.some(function(i){ return i.tag.indexOf(search_key) !== -1; });
    })) {
        result.push(o);
    }
});

console.log(result);

Solution 3

Try this:

function search(term){
return
    Array.filter(array,function(item){
       return JSON.stringify(obj).indexOf(term)!=-1;
    });
}

So :

console.log(search('market'));

I hope to be helpful for you:)

Solution 4

The concatAll and concatMap definitions are taken from http://reactivex.io/learnrx/

Array.prototype.concatAll = function() {
    var results = [];
    this.forEach(function(subArray) {
        results.push.apply(results, subArray);
    });

    return results;
};

Array.prototype.concatMap = function(projectionFunctionThatReturnsArray) {
    return this.
        map(function(item) {
            return projectionFunctionThatReturnsArray(item);
        }).
        // apply the concatAll function to flatten the two-dimensional array
        concatAll();
};

function filterByTags(keyword) {
  return array.filter(function (item) {
    var allTags = item.users.concatMap(function (user) {
      return user.tags.map(function (tag) {
        return tag.tag;
      });
    });

    return allTags.some(function (tag) {
      return tag.indexOf(keyword) > -1;
    });
  });
}

console.log(filterByTags('market'));

Of course you could inline the allTags variable for more conciseness.

The filter applied to the initial array will return all items that have users whose tags contain the keyword supplied. The strategy is to build a flattened version of the users' tags and apply some on that.

Share:
10,965
slotdp02
Author by

slotdp02

Javascript. Startups. Soccer. Soda in a styrofoam cup. My wife. My kids. "Work smart AND hard" - me

Updated on June 08, 2022

Comments

  • slotdp02
    slotdp02 almost 2 years

    I have an array of objects that I want to filter by comparing a nested property to a search term.

    For example:

     var array = [
          {category: 'Business'
           users: [
                    {name: 'Sally'
                     tags: [{tag: 'accounting'}, {tag: 'marketing'},...]
                    },
                    {name: 'Bob'
                     tags: [{tag: 'sales'}, {tag: 'accounting'},...]
                    }...
                  ]
           },
           {category: 'Heritage'
            users: [
                     {name: 'Linda'
                      tags: [{tag: 'Italy'}, {tag: 'Macedonia'},...]
                     },
                     {name: 'George'
                      tags: [{tag: 'South Africa'}, {tag: 'Chile'},...]
                     },...
                   ]
           },...
        [
    

    Essentially I want to filter the base array of objects by a search terms that include characters from the tag property string in the nested objects 2 arrays down.

    So a search for 'market' would result in

    [
      {category: 'Business'
       users: [
                {name: 'Sally'
                 tags: [{tag: 'accounting'}, {tag: 'marketing'},...]
                },
                {name: 'Bob'
                 tags: [{tag: 'sales'}, {tag: 'accounting'},...]
                }...
              ]
       }
    ]
    

    Thank you.