22

I have an array of objects (objList) that each has "id" property.

I have an array of strings (idsToRemove), representing IDs of the objects to remove from objList.

I find some solution but I fear it's slow, especially with the large list of objects with lots of properties. Is there more efficient way to do this?

var idsToRemove = ["3", "1"];
var objList = [{
    id: "1",
    name: "aaa"
  },
  {
    id: "2",
    name: "bbb"
  },
  {
    id: "3",
    name: "ccc"
  }
];

for (var i = 0, len = idsToRemove.length; i < len; i++) {
  objList = objList.filter(o => o.id != idsToRemove[i]);
}

console.log(objList);

4 Answers 4

37

Turn the idsToRemove into a Set so that you can use Set.prototype.has (an O(1) operation), and .filter the objList just once, so that the overall complexity is O(n) (and you only iterate over the possibly-huge objList once):

var idsToRemove = ["3", "1"];
var objList = [{
    id: "1",
    name: "aaa"
  },
  {
    id: "2",
    name: "bbb"
  },
  {
    id: "3",
    name: "ccc"
  }
];

const set = new Set(idsToRemove);
const filtered = objList.filter(({ id }) => !set.has(id));
console.log(filtered);

Note that Array.prototype.includes and Array.prototype.indexOf operations are O(N), not O(1), so if you use them instead of a Set, they may take significantly longer.

Sign up to request clarification or add additional context in comments.

5 Comments

Not sure if the claim Set.has is O(1) is correct. Please provide an answer to this question if it is correct. stackoverflow.com/questions/55057200/…
Does it not depend on the size of the array? If the array is small, is it not better to through it than creating a new copy in memory then access it ?
You're right, if the idsToRemove has a very small number of elements, using a Set instead doesn't provide much of a benefit.
Can you explain me the difference between your syntax and this syntax: const filtered = objList.filter(o => !set.has(o.id));
@Dalibor My version uses destructuring in the argument list, whereas that version doesn't. If a function doesn't need the whole object, but only one (or some) of its properties, I like to extract that property immediately rather than having to hold on to the whole object - but both options work just fine.
4

You can use Array.includes which check if the given string exists in the given array and combine it with an Array.filter.

const idsToRemove = ['3', '1'];

const objList = [{
    id: '1',
    name: 'aaa',
  },
  {
    id: '2',
    name: 'bbb',
  },
  {
    id: '3',
    name: 'ccc',
  },
];

const filteredObjList = objList.filter(x => !idsToRemove.includes(x.id));

console.log(filteredObjList);

Comments

3

You don't need two nested iterators if you use a built-in lookup function

   objList = objList.filter(o => idsToRemove.indexOf(o.id) < 0);

Documentation:

Array.prototype.indexOf()

Array.prototype.includes()

Comments

1

Simply use Array.filter()

const idsToRemove = ['3', '1'];

const objList = [{
    id: '1',
    name: 'aaa',
  },
  {
    id: '2',
    name: 'bbb',
  },
  {
    id: '3',
    name: 'ccc',
  }
];

const res = objList.filter(value => !idsToRemove.includes(value.id));

console.log("result",res);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.