Charles Watson
Charles Watson

Reputation: 1075

Javascript function that will analyze words in a string?

I have to write a single function in javascript.

  1. Takes in a string (full sentence).
  2. Analyzes which words have the highest count of repeated letters (i.e. rabbit, happy, there, etc).
  3. Repeated letters don't have to be consecutive.
  4. Returns the one (or more if there is a tie) word(s) that had highest repeated letter count in array format.

Example:

console.log(letterRepeat("Hello there Mr. Gormoon!));

Output:

{Gormoon}

So far I have created a function that will first split words, then letters:

var wordSelector = function(str){
var wordArray = [];
wordArray.push(str.split(" ").map(function(word) {
    return word.split("");
})); 
return wordArray[0];
};

console.log(wordSelector("Hello there Mr. Gormoon!"));

Output:

[["H", "e", "l", "l", "o"], ["t", "h", "e", "r", "e"], ["M", "r", "."], ["G", "o", "r", "m", "o", "o", "n", "!"]]

So far I have had a strong idea of what needed to be done, but I am not sure how to count each letter per word then identify the max?

But once I count them, I can sort them and take the one at position wordArray[0]

Upvotes: 0

Views: 2197

Answers (3)

Wand Maker
Wand Maker

Reputation: 18762

Here is my solution.

I use String method split to split the given sentence in words by using regex that represents a non-word character. I use Array method filter to get rid of empty values from the word array.

Then, I use Array method reduce to count number of times a character repeats in a word and then to pick maximum of those repeated char counts in function maxLetterRepeat. After that, I use Array method reduce once more to pick the word with max repeated characters.

function maxLetterRepeat(str) {
  if (str) {
      charCounts = str.split('').reduce(function (acc, c) {
        acc[c] = (acc[c] || 0) + 1;
        return acc;
      }, {});

      console.log("Char counts for " + str + " => ", charCounts);

      max = Object.keys(charCounts).reduce(function(max, c) {
        return (max < charCounts[c]) ? charCounts[c] : max;
      }, 0);

      console.log('Max repeated letters in "' + str + '" ->', max);

      return [str, max];
  }
}


wordsAndMaxRepeats = "Hello there Mr. Gormoon!".split(/\W/)
        .filter( function (e) { return e.length > 0 }).map(maxLetterRepeat);
console.log("Words & Max Char Repeated count => ", wordsAndMaxRepeats);

wordWithMaxRepeat = wordsAndMaxRepeats.reduce(function (p, c) {
    return p[1] > c[1] ? p : c;
})[0];

console.log("Word with max repeated chars => " + wordWithMaxRepeat);

Output of program

Char counts for Hello =>  { H: 1, e: 1, l: 2, o: 1 }
Max repeated letters in "Hello" -> 2
Char counts for there =>  { t: 1, h: 1, e: 2, r: 1 }
Max repeated letters in "there" -> 2
Char counts for Mr =>  { M: 1, r: 1 }
Max repeated letters in "Mr" -> 1
Char counts for Gormoon =>  { G: 1, o: 3, r: 1, m: 1, n: 1 }
Max repeated letters in "Gormoon" -> 3
Words & Max Char Repeated count =>  [ [ 'Hello', 2 ], [ 'there', 2 ], [ 'Mr', 1 ], [ 'Gormoon', 3 ] ]
Word with max repeated chars => Gormoon
[Finished in 0.3s]

Upvotes: 2

user2864740
user2864740

Reputation: 61875

For step #1, simply split on whitespace - about as done.

For step #2 make a function that takes in a word (a string) and returns how many repeated letters it has - no need to return an array of letters, which is about what a string is already!

Imagine a function about like so:

function countMaxRepeats (word) {
    // Some logic to find maximum repeat count
    return ..
}

Note how this task is now one isolated task of which there are many related questions; this case is a bit different because while keeping a tally for each character, you're only interested in the 'max tally' for any individual character, much like a 'find max value' loop.

Start with this answer and adapt it to keep track fo the 'max freq value' found so far.

For step #4 take this information - now mapped with Array.map - including the repeated letter count, and then sort the array descending based on such a count. Then take the first N items from the array until 'not at the highest count'. (Technically this can be solved using the same approach as for countMaxRepeats, but variety is .. the spice of learning.)

For example:

var wordsAndRepeatCounts = words.map(function (word) {
    return {maxRepeats: countMaxRepeats(word), word: word}
};

var sortedByRepeatsDesc = wordsAndRepeatCounts.sort(orderByRepeatsFieldescending)

Then:

var maxRepeat = sortedByRepeatsDesc[0].maxRepeats
// then take from sortedByRepeats until repeat < maxRepeat

Upvotes: 2

Fox
Fox

Reputation: 2561

Since you don't have to return all of the words you can only keep the maximum and an array of the words with this maximum repetitions.

With each new word calculate the number of repeating letters and if it's lower than max move to the next word, if it's equal add it to the array and if it's bigger update the max and create a new array with this word only.

In your example it would be:

max = 2, wordArray = ["Hello"]
max = 2, wordArray = ["Hello", "there"]
max = 2, wordArray = ["Hello", "there"]
max = 3, wordArray = ["Gormoon"]

Upvotes: 0

Related Questions