Javascript Mini Linter - Nested forEach with an IF?

Ok, so I was banging my head against a wall with this one for a while…
https://www.codecademy.com/courses/learn-javascript-iterators/projects/mini-linter

I have my solution as below code which works, but I cant help but think there’s a way that it can be refactored like this:
let count = 0
For each word in betterWords
for each overusedWord in OverusedWords
if(word === overusedWord){
count++

Is there a way to do the above with forEach & IF?

const wordCount = (over) => {
  let count = 0
  betterWords.forEach(word => {
    if(word === over){
      count++
    }
  })
  return count;
}

overusedWords.forEach(word => {
  console.log(`The word "${word.toUpperCase()}" is used ${wordCount(word)} times`);  
})

.forEach() is not a very efficient tool for counting when it compares to .filter().

const wordCount = function (textArray, word) {
  return textArray.filter(x => x === word).length;
}

Yes, both methods can lead to the same outcome; no arguing that. The simplest tool is usually the one with the least horsepower, and it gets the job done with the least overhead. .forEach() has a lot of overhead when compared to .filter(). The latter has a very specific usage and expected return. The other could be doing anything and doesn’t return anything.

Thank you.

I think I can reduce mine down to something like the below then?

overusedWords.forEach(overusedWord => {
  betterWords.filter(betterWord => {
    if(overusedWord === betterWord){
    //below is just testing I'm getting what I want, I can put the counters in here:
    console.log(overusedWord+betterWord);
    }
  })    
});

.filter() is a conditional so using if inside it is rather overkill when we can simply write a comparison. There should be no other logic or procedural code in the callback, just the comparison.

.filter() returns an array of values that meet with the condition it contains. The length of the array is the count we are after.

So why does this return undefined?

const test = overusedWords.forEach(overusedWord => betterWords.filter(betterWord => overusedWord === betterWord));
console.log(test)

Remember the lesson describes what the return of forEach() is?

Yes, it executes a function once for each element, which is fine, I can see it’s doing that.

And then if I pull the filter out to test I get the expected result for the filter, I just can’t get my head around why the filter can’t go inside the forEach (or it can and i’m just missing something!?)

const test = overusedWords.forEach(overusedWord => betterWords.filter(betterWord => overusedWord === betterWord));
console.log(test)

In EVERY instance the value of test will be undefined.

A maxim of programming is to avoid complicated expressions in favor of more imperative code, at least while the blueprints are being drawn.

This is a case where writing something that works would be better as a learning experience. Set the expression aside, for the moment. We can come back to it.

Solve this without using iterators, only imperative logic. In so doing we will get a clear picture of the inputs and the outputs with everything laid bare.

Fresh eyes has me at:

let newArray = []
overusedWords.forEach(overusedWord => {
    newArray.push(betterWords.filter(betterWord => betterWord === overusedWord));});

console.log(newArray);

From there I can get the lengths of each, I’m going to continue playing around a bit until I get Key : Values with the word and the counts.

Thanks for the direction so far!

With the guidance of MTF, I can achieve the above as below:

let newArray = []
overusedWords.forEach(overusedWord => {
    newArray.push(betterWords.filter(betterWord => betterWord === overusedWord));});

newArray.forEach(word => console.log(`The word "${word[0].toUpperCase()}" is used ${word.length} times`))

I also got stuck in this task. Although my code lines are not as sophisticated and efficient as your answers I do have a question regarding my original answer. I used this code which is using inner loops:

let really = 0;
let very = 0;
let basically = 0;

for (let i = 0; i < betterWords.length; i++) {
    for (let c = 0; c < overusedWords.length; c++) {
    if (betterWords[i] === overusedWords[c]) {
      really += 1;
    } else if (betterWords[i] === overusedWords[c]) {
      very += 1;
    } else if (betterWords[i] === overusedWords[c]) {
      basically += 1 ;
    }
 }
}
console.log(really, very, basically);

Comparing my answer to the video’s I seemed to be pretty close at getting the code ‘right’ but when I executed it console displayed the following: 8 0 0

There seems to be a problem in the inner loop that is not quite adding the times that the word is used into its respective variable and I cannot see what the problem is. I’ve tried to rewrite the instruction i.e.

really = really + 1;

but I still don’t get the correct count. i have tired to specify the index in overusedWords on each of the conditionals and it still does not work. I would appreciate any insight on what the problem is.
Thank you!