3

I have a sting and need to find first character without adjacent duplicates. I wonder how to do it with regexp. Here is what i supposed should it be. For example for string=aabbbcddg answer is c.

const paragraph='aabbbcddg';
console.log(paragraph.match(/(.)\1{1}/));

or

const paragraph='aabbbcddg';
console.log(paragraph.match(/[.]{1}/));

Can you explain why my solutions don't work?

2 Answers 2

3

Your pattern (.)\1{1} (you can omit {1}) matches 2 consecutive characters in the string and does not take the following character into account.

You could match adjacent characters from the start of the string ^ and then repeat that 1+ times. Then capture in group 2 the first character:

^(?:(.)\1+)+(.)
  • ^ Start of string
  • (?: Non capturing group
    • (.)\1+ Capture any character except a newline in group 1 and repeat the backreference \1 1+ times
  • )+ Close non capturing group and repeat 1+ times (.) Match any character except a newline in group 2

Regex demo

If you want to get multiple matches and your string does not start with consecutive characters, you can omit the ^ anchor:

Regex demo

const regex = /(?:(.)\1+)+(.)/;
const str = `aabbbcddg`;
console.log(str.match(regex)[2]);

Sign up to request clarification or add additional context in comments.

8 Comments

Try the string: asadaaasdfsdf
@Thefourthbird exactly, it should have matched the a in the beginning, instead it matches the second occurrence of s in the string, ignoring a, s, a, and d which are all valid matches for "single characters"
"not duplicate char "
Sorry, my title is deceptive, if you read post i meant without adjacent duplicates
@Thefourthbird, I didn't want to, but thanks for example.
|
1

(.)\1{1} matches two of the same character.

You could replace all the (.)\1+ to get all the characters which are not followed by itself

let str = 'aabbbcddg'
let unmatched = str.replace(/(.)\1+/g, '')[0]

console.log(unmatched)

You could also use a for loop if you want to break when a match is found

let str = 'aabbbcddg',
  found;

for (let i = 0; i < str.length; i++) {
  if (str[i - 1] !== str[i] && str[i] !== str[i + 1]) {
    found = str[i];
    break;
  }
}

console.log(found)

3 Comments

It will work, but it is not an optimal solution with long strings since we will need to go through all of it's length.
@Mark since there is no wide-spread support of negative lookbehinds, it's not feasible to use pure regex for this, so you don't really have an "optimal" solution. Although if you want the most performant, then looping through the string and checking if each character is surrounded by different characters is probably the fastest you can get.
@adiga - I changed the wording a bit on your first sentence because I got what you mean but I think it was confusing "two characters followed by itself" also sound a bit like it's only matching bbb because the first two characters are followed by another b but is not matching aa because there is not a third one and I'm fairly sure that's not what you meant.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.