Mini Linter step 5

https://www.codecademy.com/paths/web-development/tracks/web-dev-js-arrays-loops-objects/modules/learn-javascript-iterators/projects/mini-linter

Hi guys,
I’ve humbly returned here in order to hopefully gain insight before jumping on the back of someone who’s far more experienced to show me a play by play in a youtube video.

I’ve been stuck on this step for the last 4 hours and cannot figure out what i’m doing wrong.
The code below is what i’ve put together for this step but the issue with this code is that the console log portion returns each iteration of the code followed by either true or false. I’m somewhat happy because it lets me know that my code is functioning correctly but what more can I do? Why is my code not spitting out a whole number when i use console.log instead of each iteration.Send Help, i’m never going to finish this career path. :sob: :sob:

let story = 'Last weekend, I took literally the most beautiful bike ride of my life. The route is called "The 9W to Nyack" and it actually stretches all the way from Riverside Park in Manhattan to South Nyack, New Jersey. It\'s really an adventure from beginning to end! It is a 48 mile loop and it basically took me an entire day. I stopped at Riverbank State Park to take some extremely artsy photos. It was a short stop, though, because I had a really long way left to go. After a quick photo op at the very popular Little Red Lighthouse, I began my trek across the George Washington Bridge into New Jersey. The GW is actually very long - 4,760 feet! I was already very tired by the time I got to the other side. An hour later, I reached Greenbrook Nature Sanctuary, an extremely beautiful park along the coast of the Hudson. Something that was very surprising to me was that near the end of the route you actually cross back into New York! At this point, you are very close to the end.'; let overusedWords = ['really', 'very', 'basically']; let unnecessaryWords = ['extremely', 'literally', 'actually' ]; // splitting the initial story into sperate elements let storyWords = story.split(' '); //log the number of words in new story; console.log(storyWords.length); //Iterateover the unnecessary words const betterWords = storyWords.filter(word => { if (unnecessaryWords.includes(word) === false) { return word; } }); for (let i=0; i<overusedWords.length; i++) { const totalUsed = betterWords.filter(word => { return word === overusedWords[i]; }); console.log('The total times ' + overusedWords[i] + ' was used: ' + totalUsed.length); }; for (let i=0; i<storyWords.length; i++) { const numSentences = storyWords.some(periods => { if (periods.includes('.') || periods.includes('!')) { return periods === storyWords[i]; } }); console.log(numSentences) };

A filter only takes a predicate function, a conditional, and nothing else. We don’t use if in the function, or even a statement of any kind. A simple condition in the form of an expression is all that is required or expected.

c = a.filter(x => ! b.includes(x))

c will not have any of the words in b.


Later

Considering the need to preserve the original sentence structure and punctuation. Linting is done with a scalpel, not a sword. Still giving this some thought.

We do need a reliable list of the words, themselves so will spin one off and hold it at the side.

There is one instance of an escaped character in a contraction which it won’t hurt to replace with the word, ‘is’`.

story = story.replace("\'s", "is")

Apart from the words that will be removed, it is the only other edit of the story.

Now to get a list of the actual words, with no punctuation,

const storyWords = story.split(/\W+/).map(x => x.toLowerCase())

The console will likely limit the number of logged items. We can inspect it as a raw string without diffiuculty…

console.log(storyWords.toString())

last,weekend,i,took,literally,the,most,beautiful,bike,ride,…

The array is still intact. We can use it to make changes to the story string.

storyWords.forEach(x => {
  if (unnecessaryWords.includes(x)) {
    story = story.replace(x, "");
  }
})
console.log(story)

We still have all the original punctuation and capitalization, and only a small handful of edits. Since the story has changed, we could do another scan of it, like at first, or simpler still, filter the words out of storyWords, a more sensible thing to do. That will give us an accurate log of the raw words, as before.

storyWords = storyWords.filter(x => ! unnecessaryWords.includes(x))

Just realized that this approach diverges from the instructions. Oops. Should I play it out while you work on your problem?


Noticed that the overusedWords is only logging their counts…

const log = []
overusedWords.forEach(function (x) {
  const u = [x, 0]
  const z = storyWords.filter(y => y === x).length
  u[1] += z
  this.push(u)
  console.log(
    `${x} is used ${z} time${z > 1 ? 's' : ''}.`
  )
}, log)
console.log(log)

This gives us formatted output and a log of the counts for future use.


Since we are editing the string directly, if follows we would need a copy of the original for comparison. Not a problem. JS supports associative assignment. (needs more corroboration).

let backup = story = '...'

This is right to left associativity. The string is assigned to story, and a copy of story is assigned to backup. Cool, eh? Proviso, style guides suggest not doing this. But, hey. It’s still cool, right?


We’ve got one word repeated twice, which is not so annoying as the one that is repeated five times. One suspects this exercise is asking us to remove every other occurrence. Is that the case? We have the data to use for that purpose.


Addendum

Because we did one stylistic edit by removing the contraction, it comes down to the editorial decision of whether to put it back, for authenticity. There is no valid reason to edit it, beyond the mechanics employed to this point. My vote is to put it back.

For that we have the backup.

const i = backup.indexOf("\'s")
const q = backup.length - story.length;
const r = story.indexOf('It is', i - q)
story = story.slice(0, r) + " It'" + story.slice(r + 4)
console.log(story)

We’ve determined how much the string has shrunk, and set a starting point that should be pretty close to the occurrence in the edited string. That’s the i - q. Turns out we were in putting range. Got the index and executed a slice plus insertion plus slice assignment.

Bottom line, we did this with minimal storage and made good use of it. All actions took place on the story object (a string). We don’t have any remnants beyond the copy and the array of words (and a few variables). Inside a function there would be no footprint left over.

Left out the sentence count…

console.log(story.split(/[!?:.]+/).length)    //  13