In a recent project using .NET 3.5 and C# I needed to print out a long list of integers for the UI. This is of course quite trivial, but I also wanted to make it easy to read by replacing all consecutive numbers with a hyphen. For example a list of integers like this 1,2,3,4,5,7,8,10,11, should print out as 1-5, 7-8, 10-11.
I wrote the following extension method on the the IEnumerable<int> interface to accomplish this. You can download it.
Update: Modified algorithm to run in O(n) instead of O(n2) time.
{
public static string GetOrderedSetValues(this IEnumerable<int> list)
{
var orderedSet = list.OrderBy(x => x).Distinct().ToList();
var returnValue = new StringBuilder(orderedSet.Count * 2);
for (int currentIndex = 0; currentIndex < orderedSet.Count; currentIndex++)
{
if(IsEndOfList(orderedSet, currentIndex))
{
returnValue.Append(orderedSet[currentIndex]);
}
else if (IsBeginningOfGroup(orderedSet, currentIndex))
{
returnValue.Append(orderedSet[currentIndex]);
if (IsEndOfGroup(orderedSet, currentIndex))
{
returnValue.Append(“, “);
}
else
{
returnValue.Append(“-“);
}
}
else
{
if (IsEndOfGroup(orderedSet, currentIndex))
{
returnValue.Append(orderedSet[currentIndex]);
returnValue.Append(“, “);
}
else
{
//do nothing, ie. middle of grouping
}
}
}
return returnValue.ToString();
}
private static bool IsBeginningOfGroup(IList<int> list, int index)
{
if (index == 0) { return true; }
bool precedingExists = list[index] – 1 == list[index -1];
return !precedingExists;
}
private static bool IsEndOfGroup(IList<int> list, int index)
{
if (index == list.Count – 1) { return true; }
bool succeedingExists = list[index] + 1 == list[index + 1];
return !succeedingExists;
}
private static bool IsEndOfList(IList<int> list, int index)
{
return list.Count == index + 1;
}
}