1

I need to match a string with specific letters but none of the letters should be duplicated. For example, [AEIOU] should not match 'AAEIOU' or 'AAEEIOU'. It should only match 'AEIOU' and the order of the letters should not matter. I tried using the exact quantifier with {} but did not work.

2
  • So you want to check if any string has duplicate letters ex ('aaxds' - true, 'hdks' - false, 'kshk' - true)? Or only if the duplicate it right next to the same character? Or is it only the one string 'AEIOU' Commented Mar 22, 2018 at 3:01
  • You might not need regex for this.... You could filter on something like all(s.count(char) == 1 for char in 'AEIOU') probably a simpler solution than that. Can you provide some expected inputs and outputs? Commented Mar 22, 2018 at 3:01

3 Answers 3

2

You can use negative lookahead:

^(?!.*(.).*\1)[AEIOU]+$

Whatever you put in the brackets will be the subset of characters you select from.

>>> import re
>>> tests = ['AAEIOU', 'AAEEIOU', 'AEIOU']
>>> for test in tests:
..    print(re.match(r'^(?!.*(.).*\1)[AEIOU]+$', test))
None
None
<_sre.SRE_Match object; span=(0, 5), match='AEIOU'>
Sign up to request clarification or add additional context in comments.

3 Comments

Good reference link with test cases. Excellent.
I have this regex saved for reference, pretty sure this is almost a duplicate. Just can't find the original.
really good regex, can you explain it a little bit, I know what is lookaround but I didn't understand this one
0

This maybe inefficient, but maybe use counters? Construct a counter for each, then check if they are equal?

Comments

0

Not using regex, but you can use python string methods to count characters in a string. This can be used to develop a filter function that, effectively, can get you the results you want.

def has_all_unique(s):
    """Returns True of the string has exactly 1 of each vowel"""
    return all(s.count(char) == 1 for char in 'AEIOU')

tests = ['AAEIOU', 'AAEEIOU', 'AEIOU']

for match in filter(has_all_unique, tests):
    print(match)

Result would be just the one match meeting the condition,

AEIOU

This isn't the most performant option, but is simple and readable.

2 Comments

@MauricioCortazar appreciate your opinion, but I must disagree in this case. I love regex, it can be very expressive and take down deadly problems with a few characters... but put ^(?!.*(.).*\1)[AEIOU]+$ and all(s.count(char) == 1 for char in 'AEIOU') in front of 10 junior engineers and I think the results would speak to which one is easier to understand and describe without a reference or regex parser.
you're right, but i assume that everyone know regex

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.