How many times strings from one array exist in another array?

Viewed 62

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);

4 Answers

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)

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

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);

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);

Related