简体   繁体   English

针对所有另一个数组过滤数组

[英]Filtering array against all of another array

The $scope.categories array is being populated from a multi-select element in AngularJS. $ scope.categories数组是从AngularJS中的多选元素填充的。

$scope.categories = ["Adventure", "Strategy"]

I need to compare this array against the categories array in the items array below: 我需要将此数组与下面的items数组中的categories数组进行比较:

$scope.items = [
    {
        title: "Star Wars",
        categories: ["Adventure"]
    }, {
        title: "Star Search",
        categories: ["Adventure", "Strategy"]
    }, {
        title: "Star Trek",
        categories: ["Adventure", "Family"]
    }, {
    title: "Star Wars",
    categories: ["Family", "Strategy"]
}];

Both values in $scope.categories need to match the same values in $scope.items.categories , for the object to be pushed to an output array. $ scope.categories两个值需要匹配在$ scope.items.categories相同的值,对于该对象被推向一个输出阵列。

With the resulting $scope.filtered array being (items 1 ): 生成的$ scope.filtered数组为(项1 ):

{
  title: "Star Search",
  categories: ["Adventure", "Strategy"]
}

I have the logic until the loop needs to reiterate... but how? 我有逻辑,直到循环需要重申......但是如何?

  1. I am looping through $scope.categories 我循环遍历$ scope.categories
  2. Then looping through $scope.items 然后循环遍历$ scope.items
  3. Then looping through $scope.item.categories array of each object. 然后循环遍历每个对象的$ scope.item.categories数组。
  4. Then I am comparing the $scope.categories value against the value of $scope.item.categories 然后我反对$ scope.item.categories的值进行比较$ scope.categories

     for (var i = 0; i < categories.length; i++) { for (var j = 0; j < items.length; j++) { for (var k = 0; k < items[j].categories.length; k++) { if(categories[i] == items[j].categories[k]) { console.log("The value of " + categories[i] + ", matches " + items[j].categories[k]); } else { console.log("The value of " + categories[i] + ", is not a match"); } } } } 

Here is a JSbin example 这是一个JSbin示例

It's much simpler really: 这真的很简单:

var filtered = items.filter(function(i) {
  return categories.every(function(c) {
    return i.categories.indexOf(c) >= 0
  })
})

Array.prototype.filter iterates an array and calls a callback function for each item. Array.prototype.filter迭代一个数组并为每个项调用一个回调函数。 Each item that the callback function returns true for is included in the result array. 回调函数返回true的每个项都包含在结果数组中。

Array.prototype.every iterates an array and calls a callback function for each item, returning true if the callback for ALL items returned true, and false otherwise. Array.prototype.every迭代一个数组并为每个项调用一个回调函数,如果所有项的回调返回true,则返回true,否则返回false。

In this use case, we're filtering the items array, and the filter callback returns true when all of the categories "pass" the every callback condition, which is that the item categories contain the current ( c ) category. 在这个用例中,我们过滤items数组,当所有类别“传递” every回调条件时,过滤器回调返回true,即项目类别包含当前( c )类别。

(Here's the fixed JSBin ) (这是固定的JSBin

Here's a bit simpler solution. 这是一个更简单的解决方案。 It assumes that ordering and capitalization are precise. 它假定订购和大写是准确的。 Interestingly, filter + join solution outperforms the filter + every method. 有趣的是,过滤器+连接解决方​​案优于过滤器+每种方法。 If top-level categories (ie, var categories = ["Adventure", "Strategy"] ) is assumed to be a subset, then join() function can be combined with indexOf . 如果假设顶级类别(即var categories = ["Adventure", "Strategy"] )是一个子集,则join()函数可以与indexOf结合使用。 The solution would still be simpler and performance is still slightly better. 解决方案仍然更简单,性能仍然稍好一些。

See performance test here: http://jsfiddle.net/t3g3k7tL/ . 请参阅此处的性能测试: http//jsfiddle.net/t3g3k7tL/

var categories = ["Adventure", "Strategy"];

var items = [
    {
        title: "Star Wars",
        categories: ["Adventure"]
    }, {
        title: "Star Search",
        categories: ["Adventure", "Strategy"]
    }, {
        title: "Star Trek",
        categories: ["Adventure", "Family"]
    }, {
        title: "Star Wars",
        categories: ["Family", "Strategy"]
    }
];

var filtered = items.filter(function(element) {
    return element.categories.join("") === categories.join("");  
});

If, top level categories is a subset and not exact match, then the following solution will work: 如果顶级类别是子集而不是完全匹配,那么以下解决方案将起作用:

var filtered = items.filter(function(element) {
    return element.categories.join("").indexOf(categories.join("")) !== -1;    
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM