-1

I'm new in StackOverflow and JavaScript, I'm trying to get the first letter that repeats from a string considering both uppercase and lowercase letters and counting and obtaining results using the for statement. The problem is that the form I used is too long Analyzing the situation reaches such a point that maybe you can only use a "For" statement for this exercise, which I get to iterate, but not with a cleaner and reduced code has me completely blocked, this is the reason why I request help to understand and continue with the understanding and use of this sentence. In this case, the result was tested in a JavaScript script inside a function and 3 "For" sentences obtaining quite positive results, but I can not create it in 1 only For (Sorry for my bad english google translate)

I making in HTML with JavasScript

var letter = "SYAHSVCXCyXSssssssyBxAVMZsXhZV";
var contendor = [];
var calc = [];
var mycalc = 0;



letter = letter.toUpperCase()

console.log(letter)



function repeats(){
  for (var i = 0; i < letter.length; i++) {
    if (contendor.includes(letter[i]))   {
    }else{
        contendor.push(letter[i])
        calc.push(0)
    }

  }

  for (var p = 0; p < letter.length; p++) {

    for (var l = 0; l < contendor.length; l++) {
          if (letter[p] == contendor[l])  {
              calc [l]= calc [l]+1

          }

    }
  }


  for (var f = 0; f < calc.length; f++) {

    if ( calc[f] > calc[mycalc]) {
            mycalc = f

    }
  }

 }

repeats()

console.log("The most repeated letter its: " + contendor[mycalc]);

I Expected: A result with concise code

4 Answers4

3

It would probably be a lot more concise to use a regular expression: match a character, then lookahead for more characters until you can match that first character again:

var letter = "SYAHSVCXCyXSssssssyBxAVMZsXhZV";
const firstRepeatedRegex = /(.)(?=.*\1)/;
console.log(letter.match(firstRepeatedRegex)[1]);

Of course, if you aren't sure whether a given string contains a repeated character, check that the match isn't null before trying to extract the character:

const input = 'abcde';
const firstRepeatedRegex = /(.)(?=.*\1)/;
const match = input.match(firstRepeatedRegex);
if (match) {
  console.log(match[0]);
} else {
  console.log('No repeated characters');
}

You could also turn the input into an array and use .find to find the first character whose lastIndexOf is not the same as the index of the character being iterated over:

const getFirstRepeatedCharacter = (str) => {
  const chars = [...str];
  const char = chars.find((char, i) => chars.lastIndexOf(char) !== i);
  return char || 'No repeated characters';
};

console.log(getFirstRepeatedCharacter('abcde'));
console.log(getFirstRepeatedCharacter('SYAHSVCXCyXSssssssyBxAVMZsXhZV'));

If what you're actually looking for is the character that occurs most often, case-insensitive, use reduce to transform the string into an object indexed by character, whose values are the number of occurrences of that character, then identify the largest value:

const getMostRepeatedCharacter = (str) => {
  const charsByCount = [...str.toUpperCase()].reduce((a, char) => {
    a[char] = (a[char] || 0) + 1;
    return a;
  }, {});
  const mostRepeatedEntry = Object.entries(charsByCount).reduce((a, b) => a[1] >= b[1] ? a : b);
  return mostRepeatedEntry[0];
};

console.log(getMostRepeatedCharacter('abcde'));
console.log(getMostRepeatedCharacter('SYAHSVCXCyXSssssssyBxAVMZsXhZV'));
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • The first snippet is not working. if you give another char at start and repeat with that char in other place in the string(only 2 times). but it shows that char as max. – Syed mohamed aladeen May 15 '19 at 04:18
  • I still do not fully understand the use of regular expressions so it is very difficult to use in this case, should I investigate more about it? – EscaliburDebian May 15 '19 at 04:19
  • @SyedMohamedAladeen The first snippet is working fine - if another character is put at the beginning, and it occurs elsewhere in the string as well, then that character will indeed be the **first repeated character** in the string – CertainPerformance May 15 '19 at 04:20
  • @EscaliburDebian As you can probably see from the code, using regular expressions can let you match the first repeated character much more concisely than the long code in your question - they're perfect for concise pattern-matching, and you said that you wanted more concise code, so it's probably something to look into. – CertainPerformance May 15 '19 at 04:21
  • 1
    I think he needs max repeated chars. as he mentioned in the question. but still the question is unclear the snippet there is working fine as expected, gives max char of the string. – Syed mohamed aladeen May 15 '19 at 04:22
  • You could use a simpler regex: letter.match(/(\w)\1+/ig) I mean it's not necessary to use Lookarounds. It's simpler to use a Backreference. – Ali Doustkani May 15 '19 at 04:23
  • 1
    @AliDoustkani That will only match *consecutive* repeated characters, but not, for example, `aba` – CertainPerformance May 15 '19 at 04:24
  • @SyedMohamedAladeen how say CertainEntertaiment, i lookin for a more concise code but the expresion regulars for me its very hard to now for apply and sorry if the question its not make correctly i edit now the content. Very Thanks! – EscaliburDebian May 15 '19 at 04:29
  • `getMostRepeatedCharacter('abcde')` returns `A` ? – Raptor May 15 '19 at 04:41
  • @Raptor Eh, there aren't any repeating characters. Not sure what OP's looking for in that situation (or if he actually wants only the first repeating character) – CertainPerformance May 15 '19 at 04:46
  • @Raptor it's indeed the most repeated character. Unless there are more requirement, `a` is a valid output there. – VLAZ May 15 '19 at 05:13
  • @VLAZ `a` or `A`? In JS world, they are different. That's what I want to point out. – Raptor May 15 '19 at 07:27
  • @Raptor sorry, meant `A`. But it matters little - all characters are uppercased for the sake of case insensitivity and OP does seem to want a case-insensitive version. – VLAZ May 15 '19 at 07:32
1

If the first repeated character is what you want, you can push it into an array and check if the character already exists

function getFirstRepeating( str ){
    chars = []
    for ( var i = 0; i < str.length; i++){
        var char = str.charAt(i);
        if ( chars.includes( char ) ){
            return char;
        } else {
            chars.push( char );
        }
    }
    return -1;
}

This will return the first repeating character if it exists, or will return -1.

Working

function getFirstRepeating( str ){
  chars = []
  for ( var i = 0; i < str.length; i++){
    var char = str.charAt(i);
    if ( chars.includes( char ) ){
      return char;
        } else {
      chars.push( char );
        }
    }
  return -1;
}

console.log(getFirstRepeating("SYAHSVCXCyXSssssssyBxAVMZsXhZV"))
BlackPearl
  • 1,662
  • 1
  • 8
  • 16
0

Have you worked with JavaScript objects yet?

You should look into it.

When you loop through your string

let characters = "hemdhdksksbbd";
let charCount = {};
let max = { count: 0, ch: ""}; // will contain max 
                                                 // rep letter

 //Turn string into an array of letters and for 
  // each letter create a key in the charcount 
 // object , set it to 1 (meaning that's the first of 
 // that letter you've found) and any other time 
 // you see the letter, increment by 1.

characters.split("").forEach(function(character)
{
    if(!charCount[character])
        charCount[character] = 1;
    else
        charCount[character]++;
}
 //charCount should now contain letters and 
  // their counts.
  //Get the letters from charCount and find the 
  // max count
Object.keys(charCount). forEach (function(ch){

        if(max.count < charCount[ch])
              max = { count: charCount[ch], ch: ch};
 }
console.log("most reps is: " , max.ch);
0

This is a pretty terrible solution. It takes 2 loops (reduce) and doesn't handle ties, but it's short and complicated.

Basically keep turning the results into arrays and use array methods split and reduce to find the answer. The first reduce is wrapped in Object.entries() to turn the object back into an array.

let letter = Object.entries(
               "SYAHSVCXCyXSssssssyBxAVMZsXhZV".
               toUpperCase().
               split('').
               reduce((p, c) => {
                 p[c] = isNaN(++p[c]) ? 1 : p[c];
                 return p;
               }, {})
             ).
             reduce((p, c) => p = c[1] > p[1] ? c : p);

console.log(`The most repeated letter is ${letter[0]}, ${letter[1]} times.`);
Will
  • 3,201
  • 1
  • 19
  • 17