Regex 101 Answer I3 – Expand ranges in a string


Sorry about the lateness of this one. I had a meeting on Friday afternoon, and then had some things to take care of today. So anyway…


I3 – Expand ranges in a string


Given a string like:


1,2,4,6-9,12,15-17,20


expand the ranges, so the final string is:


1,2,4,6,7,8,9,12,15,16,17,20


 


Answer:


This is a fun one, because it uses a .NET regex capability that isn’t in a versions of regex. If you look at the docs for Regex.Replace, you’ll see that there’s a version like this:


public string Replace(string, MatchEvaluator);


When the regex engine finds a match, it calls into the MatchEvaluator delegate to do the substitution. So, to match a range, we’ll use a regex like:


(?<Start>\d+)\-(?<End>\d+)


 and then, we use the following method as the MatchEvaluator:


static public string Evaluator(Match match) {
    int start = Int32.Parse(match.Groups[“Start”].Value);
    int end = Int32.Parse(match.Groups[“End”].Value);
    string[] values = new string[end – start + 1];
    for (int i = 0; i < values.Length; i++)
    {
        values[i] = (start + i).ToString();
    }
    return String.Join(“,”, values);
}
  


Figuring out how that works is left as an exercise to the reader.


The nice thing about using MatchEvaluator methods is that it lets you create a hybrid of regex and procedural code.

Comments (6)

  1. Maurits says:

    Interesting… I didn’t know about String.Join(…)

    How Perl-ish 🙂

    Pity there’s no automatic array of sequential numbers in C# (start .. end) or it would be uberelegant!

  2. gdn says:

    Very nice!

  3. kov says:

    As performance hinted, this functionality may not be in all common regex’s out there, but Perl has always had an "evaluate" flag that enables arbitrary procedural code in substitution expressions.

  4. Zabeard says:

    Can this solution be modified to cope with

    1-8, -5-7 => 1, 2, 3, 4, 8

    or even prefixed 0’s e.g. for the above:

    01-08, -05-07 => 01, 02, 03, 04, 08

    Or is it non-trival?