yo3hcv
yo3hcv

Reputation: 1669

c# regex match set of characters in any order only once

I need to match any combination of characters in set, in any order, but not duplicate characters. The set is "m,s,b,r,e,l,f,t" and for example

msb - valid
mbs - valid
m - valid
mmft - not valid (duplicate m)
mxel - not valid (x is not in set)

I use this tester http://regexstorm.net/tester

This is closest but will not capture all order combinations

^(?:[m]{1})|(?:[n]{1})$

For example nm will not be captured.

Any help appreciated, thank you.

Upvotes: 3

Views: 2499

Answers (2)

Dmitry Egorov
Dmitry Egorov

Reputation: 9650

If only consecutive repetitions are not allowed (like in mmft), use this regex

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

Demo: https://regex101.com/r/11pGQB/1

If any character recurrence is not allowed (like in mftm), use this:

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

Demo: https://regex101.com/r/q1bpMr/1

The key point in the both regexes is the recurrence checking lookbehind:

  • In the first case (^(?!.*(.)\1)) the match fails if there is a character immediately followed by itself ((.)\1).

  • In the second case (^(?!.*(.).*\1)) the match fails if there is a character that repeats after some other sequence ((.).*\1).

Upvotes: 3

dcg
dcg

Reputation: 4219

If you only want to know if the string is a match you can do something like:

private bool IsMatch(string str) {
    HashSet<char> set = new HashSet<char>("msbrelft"),
                  viewed = new HashSet<char>();

    foreach (var c in str) {
        if (!set.Contains(c)) return false;
        if (viewed.Contains(c)) return false;
        viewed.Add(c);
    }
    return true;
}

Upvotes: 2

Related Questions