1

I have a Javascript iteration/Regex expression that's been driving me insane and was hoping someone could provide some insight, as the challenge I'm running into seems to be something peculiar to JS. As you can see, the regex expression I have checks to see if the letter occurs 2 or more times in the string and if it doesn't then returns the letter at the specified index. However, for a string such as "testing" it will return "t" despite "t" existing twice in the string. Yet, other strings, such as "aaaaac" it will correctly return "c". I've tested it in Rubular and the Regex expression works fine, so I haven't been able to determine why it won't work in this context.

function found (str) {
  for (const number in str) {
    let regex = new RegExp( str[number] + "{2,}");
    if (!str.match(regex)) {
      return str[number]
    }
  }
}

I would greatly appreciate any insight that could be offered!

Dog
  • 2,726
  • 7
  • 29
  • 66

3 Answers3

2

t{2,} tests for two or more immediately adjacent instances of t. It matches attack and attttack but does not match testing, which never contains the two-character sequence tt.

Instead, you want something of the form t.*t, which tests for a t, followed by zero or more characters, followed by another t at some point. Try instead:

new RegExp(str[number] + ".*" + str[number]);

However, note there are several concerning properties of your code, unrelated to this issue:

  • Using a for-in loop includes all enumerable properties, which may include more than the indices of the characters in your string. If a library extends String.prototype with an enumerable property, it will be included in your loop, which could cause unexpected results. Opt for a numerical loop from 0 through str.length-1 instead.

  • Your dynamically-created regex does not sanitize input, which can cause issues if testing regex special characters like ., * or ?. See Is there a RegExp.escape function in Javascript?

apsillers
  • 112,806
  • 17
  • 235
  • 239
1

The x{n,m} regex pattern matches a sequences of x. In the word "testing", the t's are separate, and the pattern won't match them.

Search for all the appearances of the letter in the array using the global g flag, and then compare the number of matches found with your threshold (2):

function found (str) {
  for (const number in str) {
    const regex = new RegExp(str[number], 'g');
    const match = str.match(regex);
    if (!str.match(regex) || match.length < 2) {
      return str[number];
    }
  }
}

console.log(found('testing'));
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
1

The error is in your regex, it is only matching consecutive characters, and "aaaac" was one particular test. So to make work, just change it.

function found (str) {
  for (const number in str) {
    let regex = new RegExp( str[number] + ".*" + str[number]);
    if (!str.match(regex)) {
      return str[number]
    }
  }
}