最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to filter an Array with another Array - Stack Overflow

programmeradmin0浏览0评论

I have an Array of Objects:

const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }]

I have a second array containing the ID's that I want to filter out of the first Array:

const ids = [1, 2]

How do I create a new Array of Objects without the ID's found in ids.

I have an Array of Objects:

const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }]

I have a second array containing the ID's that I want to filter out of the first Array:

const ids = [1, 2]

How do I create a new Array of Objects without the ID's found in ids.

Share Improve this question edited Aug 12, 2020 at 22:33 Leopold Kristjansson 2,78434 silver badges50 bronze badges asked Aug 12, 2020 at 16:11 AntekAntek 851 silver badge4 bronze badges 2
  • Do you want a new array, or to mutate the existing one? – Guerric P Commented Aug 12, 2020 at 16:18
  • 1 Whenever there's a question asking how to perform deletions on an array, you end up with a bunch of answers showing how to make a new array and overwrite the original. Those are not equivalent operations. – user12407908 Commented Aug 12, 2020 at 16:23
Add a comment  | 

8 Answers 8

Reset to default 9

This is a fairly simple filter operation

const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];

const ids = [1, 2];

var result = array.filter( x => !ids.includes(x.id));
console.log(result);

If you need to mutate the original array you can do like this:

const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];

const ids = [1, 2];

ids.forEach(idToDelete => {
    const index = array.findIndex(({ id }) => id === idToDelete);
    array.splice(index, 1);
});

console.log(array);

If you need a new array you can do like this:

const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];

const ids = [1, 2];

const result = array.filter(({ id }) => !ids.includes(id));

console.log(result);

You could also reassign a new array to the array variable:

let array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];

const ids = [1, 2];

array = array.filter(({ id }) => !ids.includes(id));

console.log(array);

Use Array.filter :

let array = [
  {id: 1, bar: "test" },
  {id: 2, bar: "test2" },
  {id: 3, bar: "test3" }
];

let ids = [1,2];

let filteredArray = array.filter(row=>!ids.includes(row.id));

console.log(filteredArray);

Use this oneliner from lodash.

const _ = require("lodash");
let filteredArray = _.remove(array, el=>[1,2].includes(el.id))

Use filter and indexOf.

const arr = [{ id: 1, bar: 'test' }, { id: 2, bar: 'test2' }, { id: 3, bar: 'test3' }];
const ids = [1, 2];

const result = arr.filter(element => ids.indexOf(element.id) === -1);

console.log(result);

We can filter an array in JavaScript using Array filter()

const myArray = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }]
const ids = [1,2]

const resultArray = myArray.filter(item => !ids.includes(item.id));
console.log(resultArray);

In term of performance the best solution will be the next one:

let array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1,2];
const idSet = new Set();
for (const id of ids) {
 idSet.add(id);
}

array = array.filter(x => !set.has(x.id));
//const newArray if you need the initial array unmodified

In this case we perform two consequencial iteration instead of a nested one, so the time complexity will be O(n) instead of O(n^2);

##Edit

If you instead need the initial array to be mutated and not overwritten you can use this approach:

    const ids = [1,2];
    const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];

    for (const id of ids) {
    const index = array.findIndex(x => x.id == id);
    array.splice(index, 1);

}



In the second case the time complexity will be O(n*m), where n is array length and m is ids length.

I want to propose something wildly different.

In my case, I wanted to filter one list of unique IDs against another.

I was curious if regex could do it faster.

  • Such a method really only works with one-dimensional arrays of simple objects.
    • It's probably best if items a single regex 'word' (string of 0-9a-z_).
    • A list of ids works perfect.
  • array.filter works best on small datasets (1,000), usually slightly faster
  • regex worked 66% faster on large datasets (10,000)
  • regex speed advantage widens. 90% faster on 100,000.
  • On comparing two arrays of 1m items, filter didn't do anything for me after more than 90 seconds. Regex returned a result in six seconds.
  • In this case, the input is number[], and the output is string[], which works for my purposes, but you can use map to convert back to numbers if you need, .

var listlength = 10000;

function createArray() {
  let arr = new Set();

  for (let i = 0; i < listlength; i++) {
    arr.add(Math.floor(Math.random() * listlength));
  }

  return arr;
}

function filter() {
  let arr1 = Array.from(createArray());
  let arr2 = Array.from(createArray());


  let start = +new Date();
  let arr3 = arr1.filter((n) => !arr2.includes(n));

  console.log('filter', (+new Date() - start) + 'ms', arr1.length, arr2.length, arr3.length);
}

function regex() {
  let arr1 = Array.from(createArray());
  let arr2 = Array.from(createArray());

  let start = +new Date();
  let str1 = arr1.join(',') + ',';
  str1 = str1.replace(new RegExp('\\b(' + arr2.join('|') + '),', 'g'), '');

  let result = str1.split(',') // .map(e=>Number(e)); (to convert back to number[])
  result.pop();
  console.log('regex', (+new Date() - start) + 'ms', arr1.length, arr2.length, result.length);
}

for (let x = 0; x < 10; x++) {
  console.log(`try ${x}`);
  filter();
  regex();
}

On my NodeJS app, sets of 100,000, regex more than 90% faster.

发布评论

评论列表(0)

  1. 暂无评论