Does C# have built-in support for parsing strings of page numbers? By page numbers, I mean the format you might enter into a print dialog that\'s a mixture of comma and das
Here's a slightly modified version of lassevk's code that handles the string.Split operation inside of the Regex match. It's written as an extension method and you can easily handle the duplicates problem using the Disinct() extension from LINQ.
///
/// Parses a string representing a range of values into a sequence of integers.
///
/// String to parse
/// Minimum value for open range specifier
/// Maximum value for open range specifier
/// An enumerable sequence of integers
///
/// The range is specified as a string in the following forms or combination thereof:
/// 5 single value
/// 1,2,3,4,5 sequence of values
/// 1-5 closed range
/// -5 open range (converted to a sequence from minValue to 5)
/// 1- open range (converted to a sequence from 1 to maxValue)
///
/// The value delimiter can be either ',' or ';' and the range separator can be
/// either '-' or ':'. Whitespace is permitted at any point in the input.
///
/// Any elements of the sequence that contain non-digit, non-whitespace, or non-separator
/// characters or that are empty are ignored and not returned in the output sequence.
///
public static IEnumerable ParseRange2(this string s, int minValue, int maxValue) {
const string pattern = @"(?:^|(?<=[,;])) # match must begin with start of string or delim, where delim is , or ;
\s*( # leading whitespace
(?\d*)\s*(?:-|:)\s*(?\d+) # capture 'from to' or ' to', where is - or :
| # or
(?\d+)\s*(?:-|:)\s*(?\d*) # capture 'from to' or 'from ', where is - or :
| # or
(?\d+) # capture lone number
)\s* # trailing whitespace
(?:(?=[,;\b])|$) # match must end with end of string or delim, where delim is , or ;";
Regex regx = new Regex(pattern, RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);
foreach (Match m in regx.Matches(s)) {
Group gpNum = m.Groups["num"];
if (gpNum.Success) {
yield return int.Parse(gpNum.Value);
} else {
Group gpFrom = m.Groups["from"];
Group gpTo = m.Groups["to"];
if (gpFrom.Success || gpTo.Success) {
int from = (gpFrom.Success && gpFrom.Value.Length > 0 ? int.Parse(gpFrom.Value) : minValue);
int to = (gpTo.Success && gpTo.Value.Length > 0 ? int.Parse(gpTo.Value) : maxValue);
for (int i = from; i <= to; i++) {
yield return i;
}
}
}
}
}