Mini Linter - step 8

Hello!

I would like to ask you about step 8 in Mini Linter project (https://www.codecademy.com/courses/introduction-to-javascript/projects/mini-linter).

I’m completely stuck with all three ideas:

  1. For the overused words, remove it every other time it appears.
  2. Write a function that finds the word that appears the greatest number of times.
  3. Replaced overused words with something else.

Are there any ways to solve it, using only the tools, which have been mentioned in previos lessons of “Introduction To JavaScript” course?

I kindly ask you to give examples of solutions, using only the tools, which have been mentioned in previos lessons of “Introduction To JavaScript” course.

I spent a sleepless night today… Please help me! I don’t want to spend one more sleepless night :joy: I won’t be able to sleep until the solution is found :man_facepalming:

6 Likes

Hi Shumil, I was able to find a way to solve for the first idea: “For the overused words, remove it every other time it appears”

let reallyCount = 0;
let veryCount = 0;
let basicallyCount = 0;

function even(num){
  return num % 2 === 0;
}

let idea1 = storyWords.filter(function(word) {
  if (!overusedWords.includes(word)) {
    return !overusedWords.includes(word)
  } else if (word === 'really') {
    reallyCount += 1;
    if(even(reallyCount)) {
      return word
    }
  } else if (word === 'very') {
    veryCount += 1;
    if (even(veryCount)) {
      return word
    }
  } else if (word === 'basically') {
    basicallyCount += 1;
    if (even(basicallyCount)) {
      return word
    }
  }
})
console.log('Prior to removing overused words every other time it appears: \nreally count: ' + reallyCount + '\nvery count: ' + veryCount + '\nbasically count: ' + basicallyCount +'\n');

console.log(idea1.join(' '));

// everything below this point is just to troubleshoot and double check that the code above
// worked and removed each 'odd' numbered instance of the overused words array
reallyCount = 0;
veryCount = 0;
basicallyCount = 0;

idea1.forEach(function(word) {
  if (word === 'really') {
    reallyCount += 1
  } else if (word === 'very') {
    veryCount += 1
  } else if (word === 'basically') {
    basicallyCount += 1
  }
});

console.log('\nAfter removing overused words every other time it appears \nreally count: ' + reallyCount + '\nvery count: ' + veryCount + '\nbasically count: ' + basicallyCount);

I basically added a nested IF function in each of the IF/ELSE statements that I created in step 4 to count the number of time each “overused word” was counted. In that nested function, i used a modulo to determine if the counter was even or odd. if it was even, then I returned the word to my idea1 array

4 Likes

Thank you very much!

1 Like

9 posts were split to a new topic: Getting is an empty array on task 1 of Mini-linter extra credit

Hi,

Here is how i did it,

const remove = (array,word) =>{
let counter = 0;
for(i = 0; i < array.length; i ++){
if(array[i] == word){
counter ++;
if(counter % 2 === 0){
array.splice(i, 1)
}
}

}
console.log(array)
console.log(counter);
};

const wordCount = (array,word) =>{
let counter =0;

for(i = 0; i < array.length; i ++){
if(array[i].toLowerCase().replace(/[’"]+/g, ‘’) == word.toLowerCase().replace(/[’"]+/g, ‘’)){
counter ++;
}
}
return counter
}

const mostUsedWord = (wordArray) =>{
let max = 0;
let result = ‘’;
for(j = 0; j < wordArray.length; j ++){

checkWord = wordArray[j];
let currentCheckWord = wordCount(wordArray,checkWord);

if( currentCheckWord > max){
max = currentCheckWord;
result = checkWord;
}
}

console.log(result)
console.log(max)
}

1 Like

Hello. Thank you for the solutions for 1 and 2. I was also stuck… I get the first one. The second one is still too complicated :stuck_out_tongue:
Here I got the solution for 3 all explained. I think it is the easiest way, no clue how to do it with array…

--------- code is below -----------

//define a new function for overused words replacement:
function replaceOverusedWords() {
//we save story.replace(…) in story:
story = story.replace(/really/gi, “definitely”);
story = story.replace(/very/gi, “so much”);
story = story.replace(/basically/gi, “fundamentally”);
// /really/gi is a regex. it means we will change the word globally (“g” in gi) and that it is case insensitive in our case (“i” in gi).
}
//function call:
replaceOverusedWords();
//finally we log in the console. it should write out our story with replaced words:
console.log(story);

2 Likes

Please, how do you print out elements in an array and their frequencies using a forEach loop?

I’m just reposting this so I can read it a little better.

[quote=“ervinablaev, post:5, topic:400501”]

const remove = (array,word) =>{
let counter = 0;
for(i = 0; i < array.length; i ++){
if(array[i] == word){
counter ++;
if(counter % 2 === 0){
array.splice(i, 1)
}
}

}
console.log(array)
console.log(counter);
};

const wordCount = (array,word) =>{
let counter =0;

for(i = 0; i < array.length; i ++){
if(array[i].toLowerCase().replace(/[’"]+/g, ‘’) == word.toLowerCase().replace(/[’"]+/g, ‘’)){
counter ++;
}
}
return counter
}

const mostUsedWord = (wordArray) =>{
let max = 0;
let result = ‘’;
for(j = 0; j < wordArray.length; j ++){

checkWord = wordArray[j];
let currentCheckWord = wordCount(wordArray,checkWord);

if( currentCheckWord > max){
max = currentCheckWord;
result = checkWord;
}
}

console.log(result)
console.log(max)
}
1 Like

Nope. I am still totally confused by this.
This is the 3rd DAY on Mini Linter task. I’m losing my marbles. Can someone help with task 8, part 1 please? The one that suggests to delete every second occurrence of the overUsedWords.
:expressionless:
It’s on this page

So let’s have a look at your code… The example above does not leverage any iterators which I believe is part of the objective.

forEach
map
filter
includes
&c.

I found two ways to do the second challenge (finding the most used word in the string):
One way uses the “of” keyword:

const findMaxWord = string => {
let maxFreq = 0;
let maxWord = ‘’;
let words = string.split(" “);
let onlyWords = words.map(word => word.includes(”.") || word.includes("!") || word.includes(",") ? word.slice(0,-1) : word);
for (word of onlyWords) {
let tempWordCount = 0;
for (let i = 0; i < onlyWords.length; i++) {
if (word.toLowerCase() === onlyWords[i].toLowerCase()) {
tempWordCount++;
}
if (tempWordCount > maxFreq) {
maxFreq = tempWordCount;
maxWord = word.toLowerCase()
}
}
};
console.log(The most used word is: '${maxWord}', used ${maxFreq} times.);
};
findMaxWord(betterWords);

The second method is using the .filter() method, and measuring the length of array for each word:

const findMaxWord = string => {
let maxFreq = 0;
let maxWord = ‘’;
let words = string.split(" “);
let onlyWords = words.map(word => word.includes(”.") || word.includes("!") || word.includes(",") ? word.slice(0,-1) : word);
for (let i = 0; i < onlyWords.length; i++) {
let newArray = onlyWords.filter(word => word.toLowerCase() === onlyWords[i].toLowerCase());
if (newArray.length > maxFreq) {
maxFreq = newArray.length;
maxWord = onlyWords[i];
}
}
console.log(The most used word is: '${maxWord}', used ${maxFreq} times.);
};
findMaxWord(betterWords);

I hope this was helpful in any way :slight_smile:

1 Like

Welcome to the forums, @mahahassan9632856670.

That bit of code rather intrigued me to further investigate. It occurs to me we can strip each word of punctuation in one go.

A Caution to Everybody - Brief Poems by Ogden Nash

 > ogden_text = `
Consider the auk;
Becoming extinct because he forgot how to fly, and could only walk.
Consider man, who may well become extinct
Because he forgot how to walk and learned how to fly before he thinked.
`.split('\n').join(' ').split(' ')
 > words_only = ogden_text.slice(1, -1).map(word => strip(word).toLowerCase())
 > words_only
<- ["consider", "the", "auk", "becoming", "extinct", "because", "he", "forgot", "how", "to", "fly", "and", "could", "only", "walk", "consider", "man", "who", "may", "well", "become", "extinct", "because", "he", "forgot", "how", "to", "walk", "and", "learned", "how", "to", "fly", "before", "he", "thinked"]
 > 

Shel Silverstein’s Poems Live On In ‘Every Thing’

 > silverstein_text = `
So what if nobody came?
I'll have all the icream and tea,
And I'll laugh with myself,
And I'll dance with myself,
And I'll sing, "Happy Birthday to me!"
`.split('\n').join(' ').split(' ')
 >words_alone = silverstein_text.slice(1, -1).map(word => strip(word).toLowerCase())
 > words_alone
<- ["so", "what", "if", "nobody", "came", "i'll", "have", "all", "the", "icream", "and", "tea", "and", "i'll", "laugh", "with", "myself", "and", "i'll", "dance", "with", "myself", "and", "i'll", "sing", "happy", "birthday", "to", "me"]
 > 

Now we know there is no such word or contraction, i'll so that would need to be addressed, but we’re getting somewhere.

 > words_alone = words_alone.map(word => word.replace("i'll", "I'll") || word)
 > words_alone
<- ["so", "what", "if", "nobody", "came", "I'll", "have", "all", "the", "icream", "and", "tea", "and", "I'll", "laugh", "with", "myself", "and", "I'll", "dance", "with", "myself", "and", "I'll", "sing", "happy", "birthday", "to", "me"]

It’s important to note that I am using a function, strip() which I adapted from,

Matching Word & Non-Word Character

function strip(str) {
    return str.replace(/^[\s\W]+|[\s\W]+$/g, '');
}

It uses a regular expression with the String.replace() method, both of which you may be unfamiliar. A worthwhile segue is in order, though it should not dissuade you from other approaches. I merely bring this up as a mind-expander since it only came to me upon reading your post.

1 Like

Some notes on the above code.

.slice(1, -1)

That’s because there are two empty strings in the result and this gets rid of them. They are the first and last line of string text, namely,

    ` (no text after)
    ` (no text before)
.split('\n').join(' ').split(' ')

Chrome doesn’t play well with the Regex pattern and inserts carriage return characters even though white space has been filtered out. To get around this I remove the newline characters manually above, then join it all into one long string, space separated, then split it again.

/^[\s\W]+|[\s\W]+$/g

This translates to,

/^...

at the beginning, OR,

...$/

at the end.

The | is the OR operator.

[\s\W]

is a class that includes both white space and non-word characters, in any order, independent of each other. They are both members of that class is their only distinction.

+

is the quantifier that essentially says, all

/g

is the global (or greedy) flag. It means apply the pattern to the entire sample, however long.

Oh yeah,

word => word.replace("i'll", "I'll") || word

|| word is more for documentation than logic since it never applies. The reader can see it’s going to be either one or the other, though, so I thought that was cool to include.

1 Like

It looks like we fell off the wheels by not even discussing .includes(). Pardon me for that. It’s not been forgotten. Now I don’t know this for sure, but given what we’ve seen above, we should be looking for ways to implement the method in similar fashion with a single stroke, not chained up in sequence.

Something you think we might pursue?

1 Like

Thank you for replying :slight_smile: I was actually wondering other ways to do this; I checked out the link you sent about regex, and I’m so excited to learn more about it! I’m hoping to learn how I can use this to only temporarily remove the punctuation marks, because when I run the function, the paragraph has just become one big sentence.

1 Like

Be sure to share what you learn! I’ve tried and failed many times on this problem and my attention span is getting shorter by the year.

One way is to preserve the original. When trying to reassemble it will take multiple comparisons to reconstruct. This only works if you have the original to compare to.

1 Like

Think how split and join relate. We can only join an array into its original string if we know the separator that split it, else we’re lost.

I’ve been trying to run this piece of code, and it’s not working for some reason. When the story prints, all the punctuation is still there… can you please help me figure what’s wrong with it?

function strip(string) {
let words = string.split(" “);
words.forEach(word => word.replace(/^\W+|\W+$/g, “”));
words.join(” ");
};
strip(finalStory);
console.log(finalStory);

Note how above the strip() function is very simple and only applies to one word segment at a time. We’ll want to keep it confined to that one purpose.

I’m not sure the forEach line is mutating the words array.

 > words = ['a','b','c']
<- (3) ["a", "b", "c"]
 > words.forEach(word => word.toUpperCase())
<- undefined
 > words
<- (3) ["a", "b", "c"]

Break the problem down and test each step. Work on a side problem in a sandbox, rather than in the lesson shell. You may need to work backwards through your code there, or reset to get back to the beginning.


Examine how we might use forEach in this situation…

 > words = ["a", "b", "c"]
<- (3) ["a", "b", "c"]
 > wrds = words.slice()
<- (3) ["a", "b", "c"]
 > wrds.forEach((word, index) => words[index] = word.toUpperCase())
<- undefined
 > words
<- (3) ["A", "B", "C"]

I say, ‘might’, but really mean we would look for a better way.

1 Like

Yeah so I just realized I was simply using the wrong method – it should’ve been .map() and not .forEach(), then had to assign it to a new variable. Thank you for all your help!

1 Like