why this 'repeated character" finding function doesn't work properly?

Viewed 84

JavaScript
This is the function which will give the output "true"if there is a repeated character in a string,, otherwise it will give output "false"

function repeatChar(str) {
  for (let char of str.toLowerCase()) {
    if (str.indexOf(char) !== str.lastIndexOf(char)) {
      return true;
    }
  }
  return false;
}
console.log(repeatChar('aA')); //expected output "true" but here output is "false"... Why??

7 Answers

You're searching for the lowercased character in the original string, which hasn't been converted to all lowercase.

You should replace str with its lowercase version before the loop.

function repeatChar(str) {
  str = str.toLowerCase();
  for (let char of str) {
    if (str.indexOf(char) !== str.lastIndexOf(char)) {
      return true;
    }
  }
  return false;
}
console.log(repeatChar('aA')); //expected output "true" but here output is "false"... Why??

Because str.toLowerCase() is ‘aa’ but you’re comparing occurrences in the original string ‘aA’:

// str is still ‘aA’
// str.toLowerCase() returns a *new string* and leaves str unchanged

str.indexOf(char) // “aA”.indexOf(‘a’) === 0
str.lastIndexOf(char) // “aA”.indexOf(‘a’) === 0

When you reference "str.indexOf(char)" in the "if" check you are not referencing the lower case version of str, but rather the original version with upper case.

If you want to reference the lower case version, you can do the following:

function repeatChar(str) {
  for (let char of lower_str=str.toLowerCase()) {
    if (lower_str.indexOf(char) !== lower_str.lastIndexOf(char)) {
      return true;
    }
  }
  return false;
}
console.log(repeatChar('aA'));

A simpler way to do this would be to construct a Set from the string's characters and compare its size with the original string's length. If they are equal, then there were no repeated characters, as Sets contain only unique values.

function repeatChar(str) {
     return new Set([...str.toLowerCase()]).size !== str.length;
}
str='aA';

str.toLowerCase() is 'aa';

However, unless str is updated i.e. str=str.toLowerCase(), all references to str shall be to its original form i.e. 'aA'.

And, as you rightly know (given you are indeed attempting to use uniform case during comparison), the indexOf() and lastIndexOf() methods are case sensitive

In this example I split the string into an array then loop over each element of the array. I stored the previous character in the last variable.

function repeatChar(str) {
  let last = '';
  for (const char of str.toLowerCase().split('')) {
    if (char === last) {
      return true;
    }
    last = char;
  }
  return false;
}
console.log(repeatChar('aA'));

str.toLowerCase() will not change str

Related