Use this helper class to convert back and forth between number lists and range strings.
This copies implementation of ConvertRangeStringToNumberList()
from here and ConvertNumberListToRangeString()
from here with slight improvements.
using System;
using System.Collections.Generic;
using System.Linq;
public static class NumberRangeHelper
{
/// <summary>
/// Converts a string of comma separated list of numbers and ranges to the list of individual numbers it represents.
/// </summary>
/// <param name="numbers">Range in form of <c>"2,4-8,11,15-22,39"</c></param>
/// <returns>A list of numbers</returns>
public static List<int> ConvertRangeStringToNumberList(string numbers)
{
var numbersSplit = numbers.Split(',');
var convertedNumbers = new SortedSet<int>();
foreach (var strNumber in numbersSplit)
{
int number;
if (int.TryParse(strNumber, out number))
{
convertedNumbers.Add(number);
}
else
{
// try and delimited by range
if (strNumber.Contains('-'))
{
var splitRange = strNumber.Split('-');
if (splitRange.Length == 2)
{
int firstNumber;
int secondNumber;
if (Int32.TryParse(splitRange[0], out firstNumber) &&
Int32.TryParse(splitRange[1], out secondNumber))
{
for (var i = firstNumber; i <= secondNumber; ++i)
{
convertedNumbers.Add(i);
}
}
}
}
}
}
return convertedNumbers.ToList();
}
/// <summary>
/// Converts a list of numbers to their concise range representation.
/// </summary>
/// <param name="numbers">A list of numbers such as <c>new[] { 1, 2, 3, 4, 5, 12, 13, 14, 19 }</c></param>
/// <returns>A string like <c>"1-5, 12-14, 19"</c></returns>
public static string ConvertNumberListToRangeString(IEnumerable<int> numbers)
{
var items = new SortedSet<int>(numbers)
.Select((n, i) => new { number = n, group = n - i })
.GroupBy(n => n.group)
.Select(g => (g.Count() >= 3)
? g.First().number + "-" + g.Last().number
: String.Join(", ", g.Select(x => x.number))
)
.ToList();
return String.Join(", ", items);
}
}
Test:
Action<IEnumerable<int>> DumpList = l => Console.WriteLine("\t[{0}]", String.Join(", ", l));
Action<string> DumpRange = s => Console.WriteLine("\t\"{0}\"", s);
var numbers = new[] { 1, 1, 2, 3, 4, 5, 12, 13, 19, 19, 6, 7 };
DumpList(numbers);
var str = ConvertNumberListToRangeString(numbers);
DumpRange(str);
var list = ConvertRangeStringToNumberList(str);
DumpList(list);
Console.WriteLine();
str = "1-5, 12, 13, 19, 20, 21, 2-7";
DumpRange(str);
list = ConvertRangeStringToNumberList(str);
DumpList(list);
str = ConvertNumberListToRangeString(list);
DumpRange(str);
Output:
[1, 1, 2, 3, 4, 5, 12, 13, 19, 19, 6, 7]
"1-7, 12, 13, 19"
[1, 2, 3, 4, 5, 6, 7, 12, 13, 19]
"1-5, 12, 13, 19, 20, 21, 2-7"
[1, 2, 3, 4, 5, 6, 7, 12, 13, 19, 20, 21]
"1-7, 12, 13, 19-21"