For a user selection I would like to provide a list of numbers that match a given regex. The regex itself is very simple it only can look like this 123[0-9][0-9] or [4-9]34.2
I found out that Fare (https://github.com/moodmosaic/Fare) is doing the job somehow. see the following example:
string pattern = "123[0-9][0-9]";
var xeger = new Xeger(pattern);
var match = xeger.Generate(); //match is e.g. "12349"
Unfortunately the Fare-lib is only giving me one possible match but not all 100 possible combination the string can have.
If you think regex is not a good idea in this case and would rather suggest a for-loop implementation that replaces chars I'm also going with that but currently I don't know how? Maybe a recursive function would be clever?
I'd rather create my own implementation than using a library. The following code does what you want to achieve.
private static Regex regexRegex = new Regex("\\[(?<From>\\d)-(?<To>\\d)]", RegexOptions.Compiled);
private static IEnumerable<string> GetStringsForRegex(string pattern)
{
var strings = Enumerable.Repeat("", 1);
var lastIndex = 0;
foreach (Match m in regexRegex.Matches(pattern))
{
if (m.Index > lastIndex)
{
var capturedLastIndex = lastIndex;
strings = strings.Select(s => s + pattern.Substring(capturedLastIndex, m.Index - capturedLastIndex));
}
int from = int.Parse(m.Groups["From"].Value);
int to = int.Parse(m.Groups["To"].Value);
if (from > to)
{
throw new InvalidOperationException();
}
strings = strings.SelectMany(s => Enumerable.Range(from, to - from + 1), (s, i) => s + i.ToString());
lastIndex = m.Index + m.Length;
}
if (lastIndex < pattern.Length)
{
var capturedLastIndex = lastIndex;
strings = strings.Select(s => s + pattern.Substring(capturedLastIndex));
}
return strings;
}
Basically, the code constructs all solutions for the regex pattern. It even computes them in alphabetical order.
Beware of the capturedLastIndex
variable. It is required as the compiler would otherwise capture the lastIndex variable, leading to incorrect results.