c0derkr
c0derkr

Reputation: 363

How to think of "forEach" instead of regular for loops?

I'm new to JS and am having trouble getting my head around the "forEach" method.


To help illustrate, let's say that I have 2 arrays.

The first: an array containing 1000 random words from the dictionary. The second: an array containing 10 "stopwords" (words that I'd like to filter out of the first array).

If I sit down and write a function that takes these two arrays parameters, my intuition would tell me to code it like this:

    function cleanSet(theSet, stoppers){
        for(var i=0;i<theSet.length;i++){
            for(var j=0; j<stoppers.length;j++){
                if(theSet[i] === stoppers[j]){
                    theSet.splice(i,1);
                }
            }
        }
        return theSet;
    }

However, when I try to use forEach while writing this program, it doesn't work:

function cleanerSet(theSet, stoppers){
    theSet.forEach(function(setWord,i){
        stoppers.forEach(function(stopper, j){
            if(theSet[i] === stopper[j]){
                theSet.splice(i,1);
            }
        });
    });
    return theSet;
}

Why isn't "cleanerSet" working the way "cleanSet" is?

Upvotes: 1

Views: 94

Answers (3)

Gyandeep
Gyandeep

Reputation: 13558

I think this is what you want to do

function cleanerSet(theSet, stoppers){
    return theSet.filter(function(setWord,i){
        return stoppers.indexOf(setWord) === -1;
    });
}

Runtime: cleanerSet([1,2,3,4,5], [2,4]) // [1, 3, 5]

Upvotes: 3

GPicazo
GPicazo

Reputation: 6676

The problem is that splice mutates your array, so you have to keep in mind that if you delete an item from the array that you are currently iterating, your index is not reset. As far as how to solve it, @Gyandeep provides a good solution. Also, in your first implementation, I think you might've meant:

theSet.splice(i,1);

Upvotes: 3

Javi Muhrer
Javi Muhrer

Reputation: 111

Within the callback you pass to the foreach function, the currently iterated value is stored in the first parameter of the function and the current index is stored in the second parameter. So when you check for equality you don't need to reference the index; simply use the parameter (i.e. setWord or stopper).

Additionally, when you call splice, the second parameter should be the number of items you'd like removed, so you need to pass 1, not 'i'.

This modified function should work:

function cleanerSet(theSet, stoppers){
    theSet.forEach(function(setWord, i){
        stoppers.forEach(function(stopper){
            if(setWord === stopper){
                theSet.splice(i,1);
            }
        });
    });
    return theSet;
}

Upvotes: 1

Related Questions