Mini Linter step 3 - Unexpected Output

Can someone explain why the output is an array list of ‘really’ from variable story than the variable numbeer that is counting the numbers of ‘really’?

let OverUsed = storyWords.filter(word =>{
for(let i = 0; i < storyWords.length; i++)
{
let numbeer = 0;
if(word === overusedWords[0]){
numbeer++
return numbeer;
}
}
});

console.log(OverUsed); // Output: [‘really’, ‘really’]

From MDN:
The filter() method creates a new array with all elements that pass the test implemented by the provided function.

Your function provided to filter is returning 1 or undefined. Since 1 is a truthy value filter believes the test is passed and ‘really’ (assuming overusedWords[0] is ‘really’) is added to the returned array. No other word is returned to the array because unless word === overusedWords[0] undefined is returned and that is a falsy value.

Remember, all functions return undefined by default - even if you don’t write it. The only return you have is in the if block. If nothing satisfies that condition nothing will happen and undefined will be returned by default.

forEach() might be a better function if your goal is to count.


Does this explain why my variable (numbeer) that I created to count wasn’t being read?

Yes. As it is written, number will only return 1. It is not counting properly. Here is why:

(inside filter() )

for(let i = 0; i < storyWords.length; i++)
{
	let numbeer = 0; // You are setting numbeer = 0 with each iteration of the for loop
	if(word === overusedWords[0]){
		numbeer++ // If the condition is met you are adding 1 to numbeer (numbeer changes from 0 to 1).
		return numbeer; // numbeer = 1. Returning 1. 
		// A function will stop running as soon as a return statement is reached. 
	}
}

Again, since you are using the filter iterator it is expecting you to provide a function with a true or false return value, but that can be any truthy or falsy value, it doesn’t have to explicitly be ‘true’ or ‘false’. Check the documentation I provided for more clarification.

filter() might not be the appropriate iterator for this problem. Or, if you insist on using filter, you can write it so the length of the returned array would be the correct count.

.filter() is a suitable iterator, but not on its own. We need a second iterator because there are two lists.

                             /------- predicate function -------\
overUsed = storyWords.filter(word => overUsedWords.includes(word))
                                     \-------- predicate -------/

Remember, .filter() and .includes() are iterators so we would not expect to see a loop inside their logic. The iterator is the loop and the object in context is supplying it values, one in each iteration.

Edit to refine the sketch

1 Like

Thanks for the feedback :slightly_smiling_face:

1 Like

You’re welcome. Let’s not rush away from this, just yet. Your code contains many of the features of a naive function that we should debug and get running. It’s never a good idea to toss something aside that isn’t working. Get it to work, then refine/refactor to eek out improvements and simplify.

storyWords = "I really believe I actually like M.A.S.H. very much I mean really" 
overUsedWords = ['really', 'actually', 'very', 'I']
overUsed = []
for (let word of storyWords.split(' ')) {
    for (let item of overUsedWords) {
        if (word === item) {
            overUsed.push(word)
        }
    }
}
console.log(overUsed.length, overUsed)
7 [ 'I', 'really', 'I', 'actually', 'very', 'I', 'really' ]

From there we can assemble a frequency table if we want each word counted.


keys = new Set(overUsed)
overUsedFreq = {}
for (let key of keys) {
  overUsedFreq[key] = 0
}
for (let word of overUsed) {
  overUsedFreq[word] += 1
}
console.log(overUsedFreq)
{ I: 3, really: 2, actually: 1, very: 1 }

Edited to correct typo - 1 to 0, and adjust counts

1 Like

Thank you, I will do that

1 Like