Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript ES6, best way to remove item from array if it exists or add if doesn't exists

I'm writing some code here to add an element on an array with the following logic

If the element exists on the array, the function should remove the element from the array and return the array without the given element, otherwise it should return the array with the given element appended on it.

Having this in mind, I'm thinking if there's a better way to do this, this is the code I've writed to do this.

function filterArray(arr, obj, key) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][key] === obj[key]) {
      const newArr = [...arr]
      newArr.splice(i, 1)
      return newArr
    }
  }
  return [...arr, obj]
}

const fruits = [
  { id: 1, fruit: "Apple" },
  { id: 2, fruit: "Banana" },
  { id: 3, fruit: "Pineapple" }
]

const removedBanana = filterArray(fruits, {
  id: 3,
  fruit: "Banana"
}, "fruit")

const addedStrawberry = filterArray(fruits, {
  id: 4,
  fruit: "Strawberry"
}, "fruit")

console.log(removedBanana) // [ { id: 1, fruit: 'Apple' }, { id: 3, fruit: 'Pineapple' } ]
console.log(addedStrawberry)
// [
//   { id: 1, fruit: 'Apple' },
//   { id: 2, fruit: 'Banana' },
//   { id: 3, fruit: 'Pineapple' },
//   { id: 4, fruit: 'Strawberry' }
// ]

There's a better way to do this on ES6?

EDIT
If possible, I want to iterate the array only one time, making an O(n) algorithm

like image 764
Ricardo Mendes Avatar asked Jan 10 '20 13:01

Ricardo Mendes


3 Answers

This approach mutates the array by looking for the index and splice if found or push the object to the array. The result has the same object reference than the handed over array.

function filterArray(array, object, key) {
    var index = array.findIndex(o => o[key] === object[key]);
    if (index === -1) array.push(object);
    else array.splice(index, 1);
    return array;
}

const
    fruits = [{ id: 1, fruit: "Apple" }, { id: 2, fruit: "Banana" }, { id: 3, fruit: "Pineapple" }];

console.log(filterArray(fruits, { id: 3, fruit: "Banana" }, "fruit"));
console.log(filterArray(fruits, { id: 4, fruit: "Strawberry" }, "fruit"));
.as-console-wrapper { max-height: 100% !important; top: 0; }

For a nonmutating approach, you could get a copy in the head of the function and perform the same as above.

function filterArray([...array], object, key) {

function filterArray(array, object, key) {
    var index = array.findIndex(o => o[key] === object[key]);
    if (index === -1) array.push(object);
    else array.splice(index, 1);
    return array;
}

const
    fruits = [{ id: 1, fruit: "Apple" }, { id: 2, fruit: "Banana" }, { id: 3, fruit: "Pineapple" }];

console.log(filterArray(fruits, { id: 3, fruit: "Banana" }, "fruit"));
console.log(filterArray(fruits, { id: 4, fruit: "Strawberry" }, "fruit"));
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 89
Nina Scholz Avatar answered Oct 20 '22 07:10

Nina Scholz


You can use Array.some() to check if the object exists, and if it does filter it out. If not, add it.

function filterArray(arr, obj, key) {
  return arr.some(o => obj[key] === o[key]) ? // if you can find the object
    arr.filter(o => obj[key] !== o[key]) // remove it
    :  
    [...arr, obj] // or add it if not
}

const fruits = [{"id":1,"fruit":"Apple"},{"id":2,"fruit":"Banana"},{"id":3,"fruit":"Pineapple"}]

const removedBanana = filterArray(fruits, { id: 3, fruit: "Banana" }, "fruit")
const addedStrawberry = filterArray(fruits, { id: 4, fruit: "Strawberry" }, "fruit")

console.log(removedBanana) // [ { id: 1, fruit: 'Apple' }, { id: 3, fruit: 'Pineapple' } ]
console.log(addedStrawberry)
// [
//   { id: 1, fruit: 'Apple' },
//   { id: 2, fruit: 'Banana' },
//   { id: 3, fruit: 'Pineapple' },
//   { id: 4, fruit: 'Strawberry' }
// ]
like image 35
Ori Drori Avatar answered Oct 20 '22 07:10

Ori Drori


There is a simple solution for this question:

function addObjToArray (arr, obj, key) {
  const resultArr = arr.filter(arrObj => arrObj[key] !== obj[key])
  if (resultArr.length === arr.length) resultArr.push(obj)
  return resultArr
}

The filter method will return an array with just objects that are different of obj[key]. If filtered array is equal to original array, it push the object to resultArr, else, just will return the initial resultArr.

This is solution from my work colleague (https://stackoverflow.com/users/12691758/guilherme-ca%c3%a7ador-monteiro).

What you think?

like image 1
Felipe Marcon Avatar answered Oct 20 '22 07:10

Felipe Marcon