使用另一个数组的元素来筛选.filter()数组

12

我有一个包含人名和他们语言能力的数组。我想对语言列传递一个过滤器,从而过滤掉不匹配的结果。

这是示例数组:

   var myArray = [["Steppen", "Spanish Polish"],
                  ["Wolf", "Spanish Polish Tagalog"],
                  ["Amanda", "Spanish"],
                  ["Ada", "Polish"],
                  ["Rhonda", "Spanish Tagalog"]];

在传递筛选器方面,它可以是一个语言或多种语言。即使从筛选器中匹配的一种语言也要返回结果。例如,"塔加路语"的筛选器应该返回 - Wolf 和 Rhonda。"西班牙语 波兰语"的筛选器应该返回所有人 - 在西班牙语或波兰语中都有匹配。

我编写了筛选函数,但出现问题了,当我传递 "塔加路语" 的筛选器时,它仅迭代到数组中的第二个单元格(西班牙语 波兰语 塔加路语),并且重复多次而不是继续前进。

我做错了什么?是否应该以不同的方式进行迭代?

 var userPassedFilter = new Array();
 userPassedFilter[0] = "Tagalog";

 newArray = consolidatedFilters(myArray, userPassedFilter);
 console.log(newArray);

 function consolidatedFilters(passedArray, passedFilter)
 {
 var filteredArray = passedArray.filter(    
    function(el)
    {
        for (var i = 0; i < passedArray.length; i++)
         {
            console.log("i is " + i);
             for (var j in passedFilter)
            {
                console.log("Passed Filter j " + passedFilter[j]);
                console.log("Passed Array  i " + passedArray[i][1]);        
                console.log("String Search " + passedArray[i][1].search(passedFilter[j]));

                if (passedArray[i][1].search(passedFilter[j]) != -1)
                {
                    return true;
                }
            }           
        }
         return false;
    }
 );     
 return filteredArray;
 }

你应该考虑使用jQuery.each()函数。http://api.jquery.com/jQuery.each/ - John Hartsock
你是在使用jQuery的.filter还是原生数组的.filter?看起来passedArray是你描述的数组,它不是一个jQuery对象。 - pimvdb
我正在使用jQuery的.filter(function)函数,根据传递的过滤器返回所需的数组。passedArray只是我上面描述的示例数组。 - firedrawndagger
@firedrawndagger:我不确定我理解了。如果 passedArray 是那个数组,那么 passedArray.filter 根本不是 jQuery 版本,而是内置的 .filter[...].filter 是原生版本,$(...).filter 是 jQuery 版本。 - pimvdb
@pimvdb 你是对的,我完全混淆了。它是本地JavaScript过滤器。 - firedrawndagger
5个回答

23

这是ES6方式的终极解决方案: 无需在另一个线程中再次搜索相同的查询。

var array1 = ['a', 'b', 'c', 'd', 'e'];
var array2 = ['b', 'd', 'f'];

array1 = array1.filter(function(item) {
  return !array2.includes(item); 
})
console.log(array1); // [ 'a', 'c', 'e' ]
console.log(array2); // [ 'b', 'd', 'f' ]


2
这应该是被选择的答案,因为它既简洁又高效。 - parismiguel
如果数组由对象组成,是否有相同有效的方法? 我目前的方法是 arr1.filter((x) => !arr2.some((y) => x.value === y.value) - Matthis Kohli

14
对我来说,你似乎把它弄得有点复杂了。
1. 迭代三次(`filter`、`for`循环和`for in`循环)。 2. 对数组使用 `for in` 循环。 3. 同时使用 `new Array` 和 `[...]`。
我稍微更新了一下,看起来这就是你想要的: http://jsfiddle.net/pimvdb/RQ6an/
var myArray = [["Steppen", "Spanish Polish"],
              ["Wolf", "Spanish Polish Tagalog"],
              ["Amanda", "Spanish"],
              ["Ada", "Polish"],
              ["Rhonda", "Spanish Tagalog"]];

var userPassedFilter = ["Tagalog"];

newArray = consolidatedFilters(myArray, userPassedFilter);
console.log(newArray);

function consolidatedFilters(passedArray, passedFilter) {
    var filteredArray = passedArray.filter(
    function(el) { // executed for each person
        for (var i = 0; i < passedFilter.length; i++) { // iterate over filter
            if (el[1].indexOf(passedFilter[i]) != -1) {
                return true; // if this person knows this language
            }
        }
        return false;
    }
    );     
    return filteredArray;
}

虽然我同意这个解决方案,但如果我没错的话,这似乎是O(n^2)。https://dev59.com/tITba4cB1Zd3GeqP5WX5 还有其他更有效的方法吗?谢谢 - Aman Gupta

3
这是一个更加通用的版本,它会删除所有在过滤数组中的元素。
function destroyer(arr) {
  // Remove all the values
  var passedArray = arr;
  var passedFilter = Array.prototype.slice.call(arguments, 1);

  var newArray = passedArray.filter(function(x){
    if(passedFilter.indexOf(x) !== -1){
      return false;
    }
    return true;
  });

  return newArray;
}


destroyer([1, 2, 3, 1, 2, 3], 3, 2);
//prints [1,1]

看起来你也是在自由编程营“寻找和摧毁”挑战期间搜索时发现了这篇文章。我一直在努力解决这个特定的挑战,你在这里的输入帮助了我对一些js逻辑的理解。 - Brian Zelip

2

我刚学习JavaScript,这是我唯一能想到的用一个数组过滤另一个数组的方法:

function filterThisByThis(arr) {
var numArgs = arguments.length; 
var newArr = [];
for (var i = 1; i < numArgs; i ++) {
newArr.push(arguments[i]); 
} // makes a new array from all arguments parsed to fuction minus the orginal array 
arr = arr.filter(function(val) {
  for (var j = 0; j < newArr.length; j++) {
   if (val == newArr[j]) {
      return false;}
  }
  return true;
  }); // uses the filter function to iterate over the orginal array taking out all values which occur in the new array 
return arr;
}  
filterThisByThis([1, 2, 3, 4, 1, 2, 3, 4], 1, 3);
// prints [2, 4, 2, 4]

1
另一个回答@millerjay的响应。
function destroyer(arr) {
    var array = arr;
    var filterArray = Array.from(arguments).slice(1);
    var filtered = arr.filter(function(val){
        return filterArray.indexOf(val) === -1;
    });
    return filtered;
}

destroyer([1, 2, 3, 1, 2, 3], 3, 2);
//prints [1,1]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接