使用值数组过滤多个属性的值

时间:2015-06-28 09:14:41

标签: javascript json underscore.js filtering lodash

所以我真的想在我之前的failed question中复制一份,因为我无法正确解释自己,因此没有得到答案(并没有真正解决我的问题)

有JSON:

[
  {
    "id": 2,
    "name": "Google",
    "country": "Sweden"
  },
  {
    "id": 3,
    "name": "Google",
    "country": "USA"
  },
  {
    "id": 9,
    "name": "Google",
    "country": "Ukraine"
  },
  {
    "id": 10,
    "name": "Bing",
    "country": "Sweden"
  }
]

我之前没想做的就是发布我到目前为止的内容并更好地解释我的需要。这就是我现在所拥有的:

 $scope.loadSearchEngines = function ($query) {
     return $http.get('search-engines.json', {cache: true}).then(function (response) {
         var tags = response.data;
         return tags.filter(function (tag) {
             return tag.name.toLowerCase().indexOf($query.toLowerCase()) != -1;
         });
     });
 };

此过滤器限制我只搜索name属性,而理想情况下我想搜索任何属性(或者,所有属性,而不是),我想像过滤器一样使用参数数组,这样每个单词都可以分别查看对象中的每个属性并找到匹配项。

在上一篇文章中,一个人为它发布了一个for循环,但这正是我想要避免的那种不直观的事情。 我知道我想要的结果是什么,但我只是想不出一种方法(lodash / underscore似乎差不多做了类似的事情,但我觉得某些地方缺少某些东西,或者我对理解这些文档非常不好)。

示例:

如果我写“谷歌瑞典”,它只会显示1个结果,如果我写“瑞典”,它会显示来自谷歌的那个和来自bing的那个。 如果我写“in”,它应该显示“bINg”和google“ukraINe”我猜。

这开始似乎不那么麻烦,但我无法用过滤器真正地围绕这个。我真的没有任何想法发帖,因为他们一直很尴尬,这对我来说是一个非常灰暗的区域。

3 个答案:

答案 0 :(得分:5)

从问题看来,您希望过滤每个项目中的值包含每个关键字的列表:

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

答案 1 :(得分:0)

版本A将整个数据集的结果整形为想要的搜索词迭代的组。

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>

B版采用不同的方法。在这里,我收集符合要求的对象。

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>

答案 2 :(得分:0)

也许是这样的(注意,可能不是最有效的)。不处理小写,但添加起来很简单。

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