Nathan Reul
Nathan Reul

Reputation: 46

Javascript Array.Splice() doesn't remove entry

I'm trying to remove an entry from an array if a certain condition is true, but when I console.log the array of objects, the object has not been removed and I'm confused why. Am I using the Splice() function correctly?

    var itemsProcessed;
people.forEach(async function(peep, index, object){

    var d = new Date();
    var currenttime = d.getTime();
    if (peep.endtime < currenttime){
        var rolesub = guild.roles.find(r => r.name == roleNameSub);

        var user2 = await client.fetchUser(peep.id);
        var member = await guild.fetchMember(user2);

        member.removeRole(rolesub);

        object.splice(index, 1);  //This seems to go wrong...

        console.log(peep.id + " Lost subscription!");
        user2.send("Your subscription ended!");

    }
    itemsProcessed++;
    if (itemsProcessed === object.length){
        SaveJson(people, "users.json");
    }
});    

Upvotes: 1

Views: 2324

Answers (2)

gkelly
gkelly

Reputation: 288

One thing you can consider and change is that when you are iterating the array, don't delete from it while iterating. Just mark the entry for deletion. Then, when you are done, filter out the ones that need to be removed.

For example:

people.forEach( (person,i) => {

   if( /* person needs to be removed from people */ ) {
       people[i] = null;  // use use array from 3rd parameter if you want to pass it in
   }
});

// then remove unwanted people

people = people.filter( person => person != null );

Or, if you don't want to set the person to null, then you can set a flag in the object instead to mark it for deletion.

Example:

people.forEach( (person,i) => {
   if( /* person needs to be removed from people */ ) {
       person.toBeDeleted = true;
   }
});

people = people.filter( person => person.toBeDeleted !== true );

What is probably an even better or cleaner approach is to not use forEach but just use filter only.

Example:

    people = people.filter( p_person => {
         if( /* person stays */ ) {
             return true;
         } else {
             return false;
         }
    });

Upvotes: 0

Adrian
Adrian

Reputation: 8597

Your problem is the fact you're splicing the same array you're iterating hence why the indexes will not be correct.

You should create a copy of the array before iterating it and remove elements from the original array by retrieving the index of the element you want to remove, take a look below.

arr.slice(0).forEach(function(item) {
    arr.splice(arr.indexOf(item), 1);
});

var arr = [{0:0},{i:1},{i:"test"},{i:"Something else"},{i:"Test"},5];
    
arr.slice(0).forEach(function(item) {

    if(item != 5)
        arr.splice(arr.indexOf(item), 1);
});
    
console.log(arr);

Upvotes: 1

Related Questions