How make a more concise code using the For statement?

123 Views Asked by At

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

There are 4 best solutions below

13
On

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

0
On

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

0
On

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
On

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