简体   繁体   中英

Return most repeated letter in a string of words using nested for loops in javascript

There are a couple of similar questions, however, I am not looking to search for a specific character or letter or find the first word with repeated letters. Also, I want to do this in straight javascript.

I am trying to build a function that takes a string as input, loops over every word in the string and returns the word with the most repeated letters. If there are multiple words with the same number of repeated letters (whether 1 or more) I want to return multiple words.

Here's what I have so far, but it is returning all words in the string, rather than only the one(s) with the most repeated letters. I'm having trouble figuring out how to only return the word(s) with the highest repeat count:

function repeatedLetterCounter(str) {
  str = str.toLowerCase();
  var wordArray = str.split(" ");

  var results = [];
  for (var i = 0; i < wordArray.length; i++) {
    var countNew = 0;
    var count = 0;
    var word = wordArray[i];
    for (var a = 0; a < word.length; a++) {
      var letter = word[a];
      for (var b = a + 1; b < word.length; b++) {
        var nextLetter = word[b];
        if (letter === nextLetter) {
          countNew += 1; 
        }
      }
    }
        if (countNew > count) {
          count = countNew;
          results.push(wordArray[i]);
        } else if (countNew === count) {
          results.push(wordArray[i]);
        }
  }
  return results;
}
console.log(repeatedLetterCounter("No, Bob ran across the Mississippi."));

Here is my fiddle .

I will not produce new code from scratch, but take your code and show where the issues are:

1. Why your code returns all words

Look at this code, where I hide some parts:

  for (var i = 0; i < wordArray.length; i++) {
    var count = 0;
    // two nested loops open and close here //
    // ...
    if (countNew > count) {
      count = countNew;
      results.push(wordArray[i]);
      // ...
    }
  }

This code shows that in each iteration you reset count to zero, so the if at the end will always be true. As a consequence you get all words in your result.

2. Counter too high

When you increase countNew you keep increasing it even when you are already checking the next character, so in the end it will total the number of all letter repetitions in the word you are looking at, without distinction.

3. Levels of counting

You currently use 2 count variables, but you actually need 3:

  • count: for the maximum number of repetition found in any word
  • countThisWordsBestLetter: the highest repetition found in the current word
  • countLetter: the repetition count for the current letter in the current word

4. Corrected code

 function repeatedLetterCounter(str) { str = str.toLowerCase(); var wordArray = str.split(" "); var results = []; var count = 0; for (var i = 0; i < wordArray.length; i++) { var word = wordArray[i]; var countThisWordsBestLetter = 0; for (var a = 0; a < word.length; a++) { var countLetter = 0; var letter = word[a]; for (var b = a + 1; b < word.length; b++) { var nextLetter = word[b]; if (letter === nextLetter) { countLetter += 1; } } if (countLetter > countThisWordsBestLetter) { countThisWordsBestLetter = countLetter; } } if (countThisWordsBestLetter > count) { // forget any words we gathered before: results = []; } if (countThisWordsBestLetter >= count) { count = countThisWordsBestLetter; results.push(wordArray[i]); } } return results; } console.log(repeatedLetterCounter("No, Bob ran across the Mississippi.")); // for this snippet only: document.write( JSON.stringify(repeatedLetterCounter("No, Bob ran across the Mississippi."))); 

First of all we can break this code into a set of small and useful functions. Also for this task you don't need a nested loop, see code below:

function getCountedLetters (letters) {
    var h = {};

    for (var i = 0, len = letters.length; i < len; ++i) {
        var letter = letters[i];
        h[letter] = h[letter] || 0;
        ++h[letter];
    }

    return h;
}

function getMaxCount (h) {
    var count = 0;

    for (var i in h) {
        if (h[i] > count) {
            count = h[i];
        }
    }

    return count;
}

function getMaxLetterCount (letters) {
    var h = getCountedLetters(letters);

    return getMaxCount(h); 
}

function repeatedLetterCounter (str) {
    var words = str.split(' ');
    var maxCount = 0;
    var result = [];
    var len = words.length;

    for (var i = 0; i < len; ++i) {
        var word = words[i];
        var currentCount = getMaxLetterCount(word);
        if (currentCount > maxCount) {
            maxCount = currentCount;
        }
    }

    for (var i = 0; i < len; ++i) {
        var word = words[i];
        var currentCount = getMaxLetterCount(word);
        if (currentCount >= maxCount) {
            result.push(word);
        }
    }

    if (result.length == 1) {
        return result[0];
    }

    return result;
}

I know this question is already has an accepted answer, but I found this an interesting challenge. Below is script I made with the requested requirements working.

function repeatedLetterCounter(str) {
  var wrd = str.split(' ');
  var ltr = 'abcdefghijklmnopqrstuvwxyz'.split('');
  var words = [], holder = [], actual = [];
  var highest = 0;
  for (var i = 0; i < wrd.length; i++) {
    holder[i] = 0;
    words[i] = wrd[i];
    for (var c = 0; c < ltr.length; c++) {
      var count = (wrd[i].match(new RegExp(ltr[c],'ig')) || []).length;
      if (count > 1) {holder[i] += count;}
    }
    if (holder[i] > highest) {highest = holder[i];}  
  }
  for (var i = 0; i < holder.length; i++) {
    if (holder[i] >= highest) {actual.push(words[i]);}
  }
  return actual;
}
var str = 'No, Bob ran across the Mississippi.';
var words = repeatedLetterCounter(str);
console.log(words);

Here it is working: https://jsfiddle.net/xsd3q6aa/

check this fiddle , I have modularized the code a bit :)

function getMaxFrequency(string) 
{
    var freq = {};
    var maxFrequency = 0;
    for (var i=0; i<string.length;i++) 
    {
        var character = string.charAt(i);
        if (freq[character]) 
        {
           freq[character]++;
        }
        else 
        {
           freq[character] = 1;
        }
        if ( freq[character] > maxFrequency )
        {
          maxFrequency = freq[character];
        }
    }

    return maxFrequency;
};

function repeatedLetterCounter(str)
{
  var output = [];
  var arr = str.split( " " );
  var freq = [];
  var maxFrequency = 0;
  console.log(arr);
  arr.forEach( function(value, index){

     var frequency = getMaxFrequency(value);
     freq.push([index, getMaxFrequency(value)] );
     if ( frequency > maxFrequency  )
     {
       maxFrequency = frequency;
     }

  } );
  console.log(freq);
  console.log(maxFrequency);
  freq.forEach( function(value){
     console.log( value );
     if ( value[1] == maxFrequency )
     {
        output.push( arr[value[0]] )
     }

  } );
  console.log(output);
  return output;
}


console.log(repeatedLetterCounter("No, Bob ran across the Mississippi."));

using some higher order methods:

 function repeatedLetterCounter(str) { str = str.toLowerCase(); var wordArray = str.split(" "); var mapped = wordArray.reduce(function(ac, x) { var res = x.split('').reduce(function(acc, a) { if (!acc[a]) acc[a] = 0; acc[a] ++; return acc; }, {}) ac.push(res); return ac; }, []) //mapped will map each word as an object with the char as the key and count as value wordChar = mapped.map(function(x, index) { var letter = []; var count = 0; for (var i in x) { if (count > x[i]) continue; if (count === x[i]) letter.push(i); if (count < x[i]) { letter = []; letter.push(i); count = x[i]; } } return { letter: letter, count: count, word: wordArray[index] } }) //now you can sort by the count property var result = wordChar.sort((a, b) => { return b.count - a.count }); return result[0]; //this returns an object with all the info you should need } console.log(repeatedLetterCounter("No, Bob ran across the Mississippppi.")); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM