如何从一个数组中过滤掉另一个数组的所有元素

335


我想了解从另一个数组中过滤掉所有元素的最佳方法。我尝试使用筛选函数,但是我不知道如何给它要移除的值。类似于:

var array = [1,2,3,4];
var anotherOne = [2,4];
var filteredArray = array.filter(myCallback);
// filteredArray should now be [1,3]


function myCallBack(){
    return element ! filteredArray; 
    //which clearly can't work since we don't have the reference <,< 
}

如果过滤函数无法发挥作用,您将如何实现此操作?
编辑:我检查了可能的重复问题,并且对于那些容易理解JavaScript的人可能会有用。被选为好答案的答案使事情变得容易。


13
将另一个数组传递给过滤器回调函数并使用 return arrTwo.indexOf(e) === -1;代码: var filteredArr = firstArr.filter(el => secondArr.indexOf(el) === -1); (将第一个数组中不在第二个数组中的元素筛选出来的代码,可以使用上述语句实现) - Tushar
1
可能是重复的问题:.filter()使用另一个数组元素过滤数组 - Dawid Rutkowski
这两个数组都是有序的吗? - Nina Scholz
数组并非有序,而且第二个数组的元素数量是随机的。 - Robdll
24个回答

3
OA也可以按照以下ES6的方式实现。
ES6:
 const filtered = [1, 2, 3, 4].filter(e => {
    return this.indexOf(e) < 0;
  },[2, 4]);

除了箭头语法之外,这种解决方案在过滤方面有哪些ES6优势? - Carl Edwards

3

以下是一个例子

let firstArray=[1,2,3,4,5];
let secondArray=[2,3];  
let filteredArray = firstArray.filter((a) => secondArray.indexOf(a)<0);
console.log(filteredArray); //above line gives [1,4,5]


2

这完全取决于数组的类型。

对于简单的数组,例如字符串数组。您可以像@Redu和@Hugolpz指出的那样使用以下代码:

 var arr1 = [1,2,3,4],
        arr2 = [2,4],
        res = arr1.filter(item => !arr2.includes(item));
    console.log(res);

对于更复杂的数组过滤器,例如从另一个对象数组中过滤对象数组,您可以使用以下代码

function filterArray(arr1, arr2) {
  return arr1.filter(item1 => !arr2.some(item2 => item1.id === item2.id));
}

或者

function filterArray(arr1, arr2) {
  const set = new Set(arr2.map(item => item.id));
  return arr1.reduce((filtered, item) => {
    if (!set.has(item.id)) {
      filtered.push(item);
    }
    return filtered;
  }, []);
}

这两种方法都很高效,即使使用大型数组也能良好运行。但是,在处理大量数据时,使用更高性能的数据结构,例如 Map 或 HashSet,可能会更加优化。
Map
function filterArray(arr1, arr2) {
  const map = new Map(arr2.map(item => [item.id, item]));
  return arr1.filter(item => !map.has(item.id));
}

哈希集合

function filterArray(arr1, arr2) {
  const set = new Set(arr2.map(item => item.id));
  return arr1.filter(item => !set.has(item.id));
}

1
你可以编写一个通用的filterByIndex()函数,并利用TS中的类型推断来避免回调函数的麻烦:
假设你有一个数组[1,2,3,4],你想用[2,4]数组中指定的索引进行过滤(filter())。
var filtered = [1,2,3,4,].filter(byIndex(element => element, [2,4]))

byIndex函数需要元素函数和一个数组,它的样子像这样:

byIndex = (getter: (e:number) => number, arr: number[]) => (x: number) => {
    var i = getter(x);
    return arr.indexOf(i); 
}

结果如下。
filtered = [1,3]

1
以下示例使用new Set()创建一个仅包含唯一元素的过滤数组:
具有原始数据类型的数组:字符串、数字、布尔值、null、undefined、symbol:
const a = [1, 2, 3, 4];
const b = [3, 4, 5];
const c = Array.from(new Set(a.concat(b)));

对象数组:

const a = [{id:1}, {id: 2}, {id: 3}, {id: 4}];
const b = [{id: 3}, {id: 4}, {id: 5}];
const stringifyObject = o => JSON.stringify(o);
const parseString = s => JSON.parse(s);
const c = Array.from(new Set(a.concat(b).map(stringifyObject)), parseString);

1
你可以设置过滤函数来遍历“过滤器数组”。
var arr = [1, 2, 3 ,4 ,5, 6, 7];
var filter = [4, 5, 6];

var filtered = arr.filter(
  function(val) {
    for (var i = 0; i < filter.length; i++) {
      if (val == filter[i]) {
        return false;
      }
    }
    return true;
  }
); 

1
从包含对象属性的另一个数组中创建更灵活的过滤器数组

function filterFn(array, diffArray, prop, propDiff) {
    diffArray = !propDiff ? diffArray : diffArray.map(d => d[propDiff])
    this.fn = f => diffArray.indexOf(f) === -1
    if (prop) {
         return array.map(r => r[prop]).filter(this.fn)
    } else {
         return array.filter(this.fn)
    }
}

//You can use it like this;

var arr = [];

for (var i = 0; i < 10; i++) {
    var obj = {}
    obj.index = i
    obj.value = Math.pow(2, i)
    arr.push(obj)
}

var arr2 = [1, 2, 3, 4, 5]

var sec = [{t:2}, {t:99}, {t:256}, {t:4096}]

var log = console.log.bind(console)

var filtered = filterFn(arr, sec, 'value', 't')

var filtered2 = filterFn(arr2, sec, null, 't')

log(filtered, filtered2)


1
您可以使用过滤器,然后对于过滤函数,使用筛选数组的缩减,该缩减在找到匹配项时检查并返回true,然后在返回时反转(!)。过滤函数每个数组元素调用一次。在您的帖子中,函数未对任何元素进行比较。

var a1 = [1, 2, 3, 4],
  a2 = [2, 3];

var filtered = a1.filter(function(x) {
  return !a2.reduce(function(y, z) {
    return x == y || x == z || y == true;
  })
});

document.write(filtered);


1

var arr1= [1,2,3,4];
var arr2=[2,4]

function fil(value){
return value !=arr2[0] &&  value != arr2[1]
}

document.getElementById("p").innerHTML= arr1.filter(fil)
<!DOCTYPE html> 
<html> 
<head> 
</head>
<body>
<p id="p"></p>


谢谢,它可以工作,但我更喜欢保持本地范围。另外,arr2具有随机数量的元素。 - Robdll

1

function arr(arr1,arr2){
  
  function filt(value){
    return arr2.indexOf(value) === -1;
    }
  
  return arr1.filter(filt)
  }

document.getElementById("p").innerHTML = arr([1,2,3,4],[2,4])
<p id="p"></p>


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