Home > other >  Checking same case in JavaScript
Checking same case in JavaScript

Time:10-15

I was trying to solve a code wars kata called "Check same case", and I'm not understanding what is wrong with my solution and why it doesn't pass. The function should check:

  • If either of the characters is not a letter, return -1
  • If both characters are the same case, return 1
  • If both characters are letters, but not the same case, return 0

Here's my solution:

function sameCase(a, b) {
  if (!a.match(/[A-z]/g) || !b.match(/[A-z]/g)) {
    return -1
  } else if ((a.match(/[A-Z]/g) && b.match(/[A-Z]/g)) || (a.match(/[a-z]/g) && b.match(/[a-z]/g))) {
    return 1
  } else {
    return 0
  }
}

The solution passes in all the tests, but when I click on "Attempt" I get these two errors:

  • For sameCase("^","B"): expected 0 to equal -1

function sameCase(a, b) {
  if (!a.match(/[A-z]/g) || !b.match(/[A-z]/g)) {
    return -1
  } else if ((a.match(/[A-Z]/g) && b.match(/[A-Z]/g)) || (a.match(/[a-z]/g) && b.match(/[a-z]/g))) {
    return 1
  } else {
    return 0
  }
}

console.log(sameCase("^", "B"));

  • For sameCase("]","D"): expected 0 to equal -1

function sameCase(a, b) {
  if (!a.match(/[A-z]/g) || !b.match(/[A-z]/g)) {
    return -1
  } else if ((a.match(/[A-Z]/g) && b.match(/[A-Z]/g)) || (a.match(/[a-z]/g) && b.match(/[a-z]/g))) {
    return 1
  } else {
    return 0
  }
}

console.log(sameCase("]", "D"));

CodePudding user response:

As anticipated in the comments, your solution fails the tests because the range you use in your RegExp ([A-z] = from char code 65 to char code 122) includes also some non-alphabetic characters, such as the ones used in the tests: ] (char code 93) and ^ (char code 94).

That said, your solution presents also another issue as you are not checking that the arguments passed to the function are single characters rather than strings. In fact:

function sameCase(a, b) {
  if (!a.match(/[A-z]/g) || !b.match(/[A-z]/g)) {
    return -1
  } else if ((a.match(/[A-Z]/g) && b.match(/[A-Z]/g)) || (a.match(/[a-z]/g) && b.match(/[a-z]/g))) {
    return 1
  } else {
    return 0
  }
}

console.log(sameCase("0123A", "A4567")); // will return 1 because the only letter of both string is in the same case

Solution

You can solve both issues simply by tuning the RegExp:

function sameCase(a, b) {
  if (!a.match(/^[A-Za-z]$/) || !b.match(/^[A-Za-z]$/)) {
    return -1
  } else if (
    (a.match(/^[A-Z]$/) && b.match(/^[A-Z]$/)) ||
    (a.match(/^[a-z]$/) && b.match(/^[a-z]$/))
  ) {
    return 1
  } else {
    return 0
  }
}

console.log(sameCase('D', ']'));
console.log(sameCase('D', '^'));
console.log(sameCase('0123A', 'A4567'));

Although in a case like this I would tend to use RegExp.prototype.test(), which returns a boolean, because there is no real use for the array returned by String.prototype.match():

function sameCase(a, b) {
  if (!/^[A-Za-z]$/.test(a) || !/^[A-Za-z]$/.test(b)) {
    return -1
  } else if (
    (/^[A-Z]$/.test(a) && /^[A-Z]$/.test(b)) ||
    (/^[a-z]$/.test(a) && /^[a-z]$/.test(b))
  ) {
    return 1
  } else {
    return 0
  }
}

console.log(sameCase('D', ']'));
console.log(sameCase('D', '^'));
console.log(sameCase('0123A', 'A4567'));

[A-Za-z] will check that the sub-strings contain only Latin letters and the use of ^ and $ to indicate the beginning and the ending of the string will check that they are only one character each.

Note

Please ignore my comment about the use of String.prototype.charCodeAt(), as I misread the requirements and assumed the function had to check whether the two arguments were the same letter in the same case... and even in that case, you could check it with a strict equality operator (a === b) with no need to over-complicate it with charCodeAt(). I do not really know what I was thinking. :P

  • Related