Compact a comma delimited number list into ranges I'm looking for a clever way to do the following operation:

Take a list of numbers:

1, 2, 3, 4, 5, 12, 13, 14, 19

and compact it into a string like so: 

1-5, 12-14, 19

With the following rule: only compress into a range (i.e. use a dash) when the count of numbers in the range is 3 or more.

I.e.: 1, 2, 4, 5 would result in: 1, 2, 4, 5 and NOT: 1-2, 4-5

This is my implementation, but I feel like it could be improved upon greatly:

 public string CompactNumberRanges(IEnumerable&lt;int&gt; numbers, 
                                   int requiredRangeCount)
 {
     if (requiredRangeCount &lt;= 1)
         throw new ArgumentOutOfRangeException("requiredRangeCount");

     int[] sorted = numbers.OrderBy(e =&gt; e).ToArray();

     StringBuilder b = new StringBuilder();

     for (int i = 0; i &lt; sorted.Length; i++)
     {
         int cv = sorted[i];
         int count = 0;

         for (int j = cv; ; j++)
         {
             if (Array.IndexOf(sorted, j) == -1)
                 break;
             else
                 count++;
         }

         if (count == 0)
             throw new InvalidOperationException();
         else if (count &lt; requiredRangeCount)
             b.Append(", ").Append(cv);
         else if (count &gt;= requiredRangeCount)
         {
             b.Append(", ").AppendFormat("{0}-{1}", cv, sorted[i + count - 1]);

             i += count - 1;
         }
     }

     return b.ToString().Trim(',', ' '); ;
 }


As an example:

List&lt;int&gt; numbers = new List&lt;int&gt;
    (
        new int[] { 1, 2, 3, 4, 5, 12, 13, 14, 19 }
    );

Console.WriteLine(CompactNumberRanges(numbers, 3));
//  output: 1-5, 12-14, 19


I have this working fine, I'm really just looking to find better ways to do the same operation because I think it's a fun one.
You could calculate a value to group on, i.e. number - index. All consecutive numbers have the same value:

index  number  number - index
-----  ------  --------------
  0       1          1
  1       2          1
  2       3          1
  3       4          1
  4       5          1
  5      12          7
  6      13          7
  7      14          7
  8      19         11


Then you just check how many items there is in each group to determine if it should be a range.

Example:

List&lt;int&gt; numbers = new List&lt;int&gt; { 1, 2, 3, 4, 5, 12, 13, 14, 19 };

List&lt;string&gt; items = numbers
  .Select((n,i) =&gt; new { number = n, group = n - i })
  .GroupBy(n =&gt; n.group)
  .Select(g =&gt;
    g.Count() &gt;= 3 ?
      g.First().number + "-" + g.Last().number
    :
      String.Join(", ", g.Select(x =&gt; x.number))
  )
  .ToList();

Console.WriteLine(String.Join(", ", items));


Output:

1-5, 12-14, 19