Filter values of multiple properties with an array of values
From the question it looks as if you want to filter a list where the values in each item contains every keyword:
var keywords = ['Google', 'Sweden']; var result = _.filter(data, function(item){ return _.every(keywords, function(keyword){ return _.some(item, function(value){ return _.isString(value) && value.indexOf(keyword) != -1; }) }); });
Perhaps something like this (note, probably not the most efficient one). Doesn't handle lowercase, but it's simple to add.
http://jsfiddle.net/W4QfJ/520/
var stuff = [ { "id": 2, "name": "Google", "country": "Sweden" }, { "id": 3, "name": "Google", "country": "USA" }, { "id": 9, "name": "Google", "country": "Ukraine" }, { "id": 10, "name": "Bing", "country": "Sweden" }];var searchTerm = 'Google Sweden';var searchTermArr = searchTerm.split(' ');var results = [];var obj;searchTermArr.forEach(function (val, index, arr) { obj = _(stuff) .filter(function (s) { return JSON.stringify(s).indexOf(val) > -1; }).value(); results = results.concat(obj);});console.log(_.unique(results));
Version A shapes the result for the whole data set to the wanted set which iterates throu the search words.
var data = [{ "id": 2, "name": "Google", "country": "Sweden" }, { "id": 3, "name": "Google", "country": "USA" }, { "id": 9, "name": "Google", "country": "Ukraine" }, { "id": 10, "name": "Bing", "country": "Sweden" }];function search(s) { var searchA = s.split(' ').map(function (a) { return a.toLowerCase(); }); var result = JSON.parse(JSON.stringify(data)); searchA.forEach(function (a) { result = result.reduce(function (res, el) { var i; for (i in el) { if (~('' + el[i]).toLowerCase().indexOf(a)) { res.push(el); break; } } return res; }, []); }); return result;}out('search for \'google sweden\'\n' + JSON.stringify(search('google sweden'), null, 4), true);out('search for \'bing\'\n' + JSON.stringify(search('bing'), null, 4), true);out('search for \'IN\'\n' + JSON.stringify(search('IN'), null, 4), true);out('search for \'x\'\n' + JSON.stringify(search('x'), null, 4), true);function out(s, pre) { var descriptionNode = document.createElement('div'); if (pre) { var preNode = document.createElement('pre'); preNode.innerHTML = s + '<br>'; descriptionNode.appendChild(preNode); } else { descriptionNode.innerHTML = s + '<br>'; } document.getElementById('out0').appendChild(descriptionNode);}
<div id="out0"></div>
Version B with different approach. Here I collect the objects who match the requirements.
var data = [{ "id": 2, "name": "Google", "country": "Sweden" }, { "id": 3, "name": "Google", "country": "USA" }, { "id": 9, "name": "Google", "country": "Ukraine" }, { "id": 10, "name": "Bing", "country": "Sweden" }];function search(s) { var searchA = s.split(' ').map(function (a) { return a.toLowerCase(); }); return data.reduce(function (res, el) { var i, found = 0; for (i in el) { found += searchA.some(function (a) { return ~('' + el[i]).toLowerCase().indexOf(a); }); } found === searchA.length && res.push(el); return res; }, []);}out('search for \'google sweden\'\n' + JSON.stringify(search('google sweden'), null, 4), true);out('search for \'bing\'\n' + JSON.stringify(search('bing'), null, 4), true);out('search for \'IN\'\n' + JSON.stringify(search('IN'), null, 4), true);out('search for \'x\'\n' + JSON.stringify(search('x'), null, 4), true);function out(s, pre) { var descriptionNode = document.createElement('div'); if (pre) { var preNode = document.createElement('pre'); preNode.innerHTML = s + '<br>'; descriptionNode.appendChild(preNode); } else { descriptionNode.innerHTML = s + '<br>'; } document.getElementById('out').appendChild(descriptionNode);}
<div id="out"></div>