Remove elements from array and returning mutated array

Hey,

I can’t for the life of me figure out how to remove elements from an array and return the mutated array rather than the items removed.

For example…

var arr = [‘apple’, ‘banana’, ‘cake’, ‘pizza’, ‘ice cream’]
var fruits = [‘apple’, banana’, ‘melon’, ‘grapes’, ‘kiwi’]

I want to iterate through ‘arr’ and remove any term that’s in the ‘fruits’ array, but return whatever is left in the ‘arr’ array.

I know this is going to be blatantly easy, I just can’t get my head there.

Create a temporary array inside the function in which you store the things that are not in that array and return the new array?

Or maybe use of filter() and includes()?

All this methods don’t mutate the original array but return a new array with the wanted elements.
If instead you want to mutate the original array, you need a careful use of splice()

But those methods return the a new array of the removed items, do they not?

It depends on how you implement things

Good day @Dave-Melia ,

It happens.

Here is what you’re seeking to accomplish:

var arr = ['apple', 'banana', 'cake', 'pizza', 'ice cream']
var fruits = ['apple', 'banana', 'melon', 'grapes', 'kiwi'];
 
fruits.map( fruit => { 
         arr.map( (ar, index) => {        
             if (fruit == ar){ arr.splice(index,1) } 
         });
  });
 console.log(arr);

Don’t forget to indent your code.
Use let instead of var in your upcoming code :slightly_smiling_face:

@geek4ctrl nice solution but maybe you should spoler/blur that out. This isn’t the way for someone to learn :wink:

1 Like

Thanks @swcarrey

How do I insert the blur effect? :smiley:

To insert the blur effect use the spoiler tag outside the backticks

Thank you very much @ilenia :slightly_smiling_face:

elements is an array with all elements being undefined - maybe you want to use forEach instead of creating a new array like that?

here are four ‘different’ methods, although they are technically not really different but variations of each other

/* method 1 */
const filtered = arr.filter(f=>!fruits.includes(f))
console.log(filtered)

/* method 2 */
const newArr =[]
arr.forEach((a)=>{
  if(fruits.indexOf(a) == -1 ) newArr.push(a)
})
console.log(newArr)

/* method 3 */
const newArr2=[]
for (let i= 0; i < arr.length; i++){
  let flag = true;
  for(let j=0; j < fruits.length; j++){
    if(arr[i]==fruits[j]){
      flag = false;
      break;
    }
  }
  if(flag) newArr2.push(arr[i])
}
console.log(newArr2)

/* method 4 */
const obj={}
const combo=[...arr,...fruits]
combo.forEach(c =>{
  obj[c]= obj[c] ? delete obj[c] : 1
  fruits.forEach(f => {
    if (c==f && obj[c]) delete obj[c] 
  })
})
console.log(Object.keys(obj))
1 Like

Thanks @ilenia,

I modified it a bit. That should be fine now.

The whole thing can be done with a single filter():

const result = arr.filter(el => {
    // return the current element if it's NOT in fruits array
});

I think indeOf() may be useful to you here as includes() has poor browser support.

@Dereje1 if I ever saw your methods #3 and #4 in the wild, I’d want to find whoever did it and beat them round the head with a heavy refactoring stick :smile:

1 Like

You are still creating the new array even if it is not being stored anywhere

Please read again what map() does and when you don’t intend to use its features don’t use it. In this case that it is the equivalent of two nested loops just for accessing items in an array and not change them just use forEach()

I see what you implied.

I get it now.

i hear ya @swcarrey, just trying to do it as a mental exercise, method 4 is pretty ugly too

@Dereje1

lol, it’s all good. The last two methods reminded me of cleaning a tiled floor with a toothbrush rather than using the mop :smile:

1 Like

@swcarrey
haha, but I bet for very huge arrays method 3 would be the fastest, just a conjecture here…

@Dereje1

No need to bet, try it and post the results :slight_smile: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now

@swcarrey
Actually I was wrong (results below in ms), Only tested for a combined 100k elements (50k in each array) as a million was taking too long on replit

Method 1 29153
Method 2 27805
Method 3 38629
Method 4 132693
Method 5 312

Method 3 was even slower than filter et al., Method 4 was dismal, however method 5, a variation of Method 3 but with a binary search of the string instead of the inner loop was blazing

  function method5(){
    const start=Date.now()
    const newArr2=[]
    const copy = [...arr2]
    copy.sort((a,b)=> a>b ? 1: 0)
    for (let i= 0; i < arr1.length; i++){
      if(!binarySearch(copy,arr1[i])) newArr2.push(arr1[i])
    }
    console.log(`Method 5 ${Date.now()-start}`)
  }

binarySearch = (arr, target)=>{
  // arr needs sorted!!
  let lowIndex = 0
  let highIndex = arr.length - 1
  while(true){
    const mid = Math.floor((lowIndex + highIndex)/2)
    if(target==arr[mid]) return true
    if(target>arr[mid]){
      lowIndex = mid+1
    }
    else{
      highIndex = mid-1
    }
    if(highIndex<lowIndex) return null
  }
}

[https://repl.it/@Dee3/ShamelessLovingBetaversion](http://replit test)

1 Like