2

I have two arrays, storyWords, and overusedWords. I am trying to get to know, how many times an overusedWords string is in storyWords in an object format. The output should like {really: 2, very: 5, basically: 1}, however, at the moment I am getting output like {really: 1, very: 1, basically: 1}. It looping only once.

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'];

const storyWords = story.split(' ');


const objGroup = storyWords.reduce((previousValue, currentValue) => {
  overusedWords.forEach((word) => {
    if (currentValue === word) {
      previousValue[currentValue] += 1;
    } else {
      previousValue[word] = 1;
    }
  })
  return previousValue;
}, {});

console.log(objGroup);

0

4 Answers 4

3

You can use Array#includes to check if a currentValue is an overused word, and update previousValue accordingly:

const objGroup = storyWords.reduce((previousValue, currentValue) => {
  if (overusedWords.includes(currentValue)) {
    previousValue[currentValue] = (previousValue[currentValue] || 0) + 1;
  }
  return previousValue;
}, {});

Improvement: create a Set const overusedWordsSet = new Set(overusedWords); and check if a word is an overused one using overusedWordsSet.has(currentValue)

Sign up to request clarification or add additional context in comments.

2 Comments

// Why this code does not work here, will you please explain? if (overusedWords.includes(currentValue)) { previousValue[currentValue] += 1; } else { previousValue[currentValue] = 1; } return previousValue;
@MamunurRashid you only want to update previousValue if the currentValue is in overusedWords. The else here is saying that if it's not, set it's value as 1 which doesn't match with the expected output above. Besides, the if doesn't check if previousValue has such a key before incrementing it's value, which results in a NaN.
3

The default initial value for previousValue[currentValue] is undefined.

When you try to do math with undefined you get NaN. When you try to do more math - +1 on NaN - you just get NaN again.

You need to initialize the value to 0:

previousValue[currentValue] = (previousValue[currentValue] || 0) + 1;

Alternatively you can initialize that initial value you pass to storyWords.reduce(...) with all 0 values:

let overusedWords = ['really', 'very', 'basically'];

let initial = overusedWords.reduce((aggreg, oWord) => {
    aggreg[oWord] = 0
    return aggreg
}, {})

initial

Also, I don't know what that else { block is supposed to be doing:

    } else {
      previousValue[word] = 1;
    }

But it's overwriting all the values to 1

1 Comment

2

Something like the below could work. I made the assumption that you want to count words by ignoring the case, so I added a toLowerCase() call on the string comparison when checking strings in the storyWords array (overusedWords already contains lowercase strings).

const 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.';
  
const overusedWords = ['really', 'very', 'basically'];
  
const storyWords = story.split(' ');

const overusedWordCounts = {};

overusedWords.forEach((word) => {
  overusedWordCounts[word] = storyWords.filter(storyWord => storyWord.toLowerCase() === word).length;
});

console.log(overusedWordCounts);

3 Comments

The .toLowerCase() seems worthy of an explanation - it's not in the original question. Are there some assumptions you've made about what the question is trying to do, or things the OP has taken for granted?
Good point. The assumption I made was that the case should be ignored when counting the frequency of words for example basically and Basically both count.
Sounds like a good edit for your question!
-1

I think you're approaching this from the wrong side. Try using .match to check for occurrences of the word in the string rather than looping through each word.

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'];

const objGroup = overusedWords.reduce((carry, word) => {
  const regex = new RegExp(word, 'gi');
  carry[word] = story.match(regex).length;
  return carry;
}, {});

console.log(objGroup);

1 Comment

You need a word boundary in the regex or it will also match on every or ethereally

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.