0

With the following array:

randomArray = [
  {alias: 'book1', page: 127}, 
  {alias: 'book1', page: 115}, 
  {alias: 'book2', page: 115}
]

If I'd like to add an object to the array, (when order doesn't matter), I'm assuming I can simply:

randomArray.push({alias: 'book3', page: 303})

But if I want to remove an object, say for example I would like to remove: {alias: 'book1', page: 115}, how would I do this?

I've seen other stack overflow questions, like this, try to find an index of the object, but they look for one property assuming that property has unique values throughout the array.

My thought:

I wanted to try indexOf and then splice that object, but it doesn't work.

randomArray.indexOf({alias: 'book1', page: 115}) returns -1

What's an efficient way to look through an array of objects and remove an exact match? For clarity, without using a library, and all of these objects will have the same alias and id properties, no more, no less. (Also, am I supposed to call these properties or keys, or are they synonymous?)

Edit: I've changed id to page to make more sense

Community
  • 1
  • 1
James B
  • 432
  • 5
  • 22

2 Answers2

-1

Dirty solution (assuming the objects does not contain functions):

const objectToRemove = JSON.stringify({ alias: 'pepper', id: 1 });
const filteredArray = randomArray.filter(item =>
  JSON.stringify(item) !== objectToRemove);

Another solution would be to build a unique ID from the objects:

const toRemove = Object.entries({ alias: 'pepper', id: 1 }).join('-');
const filteredArray = randomArray.filter(item =>
  Object.entries(item).join('-') !== toRemove);

Or

const toRemove = 'pepper-1;
const filteredArray = randomArray.filter(item =>
  `${item.alias}-${item.page}` !== toRemove);
Léo Martin
  • 736
  • 7
  • 13
  • Clean enough for me! I've edited the original question if you would like to edit your response to make sense for future visitors. My edits were changing the `alias`'s to `books`'s and the `id`'s to `page`'s. Will mark correct when time limit is up – James B Dec 12 '19 at 22:59
  • 1
    Will work the same way, just update the objectToRemove accordingly :) – Léo Martin Dec 12 '19 at 23:00
-1

JSON.stringify and joins are both very dirty solutions and both rely on the properties being in the same order, use a deep object compare function and then you can just use a filter to return an array that doesn't contain the item you want to remove.

const compare = (obj1, obj2) =>
  Array.isArray(obj1)
    ? Array.isArray(obj2) && obj1.length === obj2.length && obj1.every((item, index) => compare(item, obj2[index]))
    : obj1 instanceof Date
    ? obj2 instanceof Date && obj1.getDate() === obj2.getDate()
    : obj1 && typeof obj1 === 'object'
    ? obj2 && typeof obj2 === 'object' &&
      Object.getOwnPropertyNames(obj1).length === Object.getOwnPropertyNames(obj2).length &&
      Object.getOwnPropertyNames(obj1).every(prop => compare(obj1[prop], obj2[prop]))
    : obj1 === obj2;
    
const randomArray = [
  {alias: 'book1', page: 127}, 
  {alias: 'book1', page: 115}, 
  {alias: 'book2', page: 115}
];

console.log(randomArray.filter(item => !compare(item, {alias: 'book1', page: 127})));
Adrian Brand
  • 20,384
  • 4
  • 39
  • 60
  • Could you provide context on what "dirty solution" means? For this question, the properties will always be in the same order. I ask because this question was posted after the first answer was marked correct, and someone has downvoted it. – James B Dec 13 '19 at 14:34
  • What an overcomplicated solution when you can simply build an unique compound index from a given object – Léo Martin Dec 14 '19 at 22:56
  • When you already have the deep compare function in your project it is a simple solution. If you know it is just alias and page properties then it is overkill but this solution works for any array. – Adrian Brand Dec 15 '19 at 02:11
  • @LéoMartin I have used your solution. I do not understand why people are downvoting a solution (yours) that works perfectly for my given task. – James B Dec 16 '19 at 13:41
  • Dirty means that turning objects into strings to compare them is very inefficient. If there are only two properties the most efficient solution is randomArray.filter(item => item.alias !== remove.alias && item.page !== remove.page) – Adrian Brand Dec 16 '19 at 22:33