Separate range of numbers, if in sequence then by hyphen, and if break in sequence occurs then comma character

I think the loop-within-loop is making things more confusing. Try using just a single loop, because you only need to iterate over the entire list once.

int start,end;  // track start and end
end = start = arr[0];
for (int i = 1; i < arr.Length; i++)
{
    // as long as entries are consecutive, move end forward
    if (arr[i] == (arr[i - 1] + 1))
    {
        end = arr[i];
    }
    else
    {
        // when no longer consecutive, add group to result
        // depending on whether start=end (single item) or not
        if (start == end)
            result += start + ",";
        else if (end == (start + 1))
            result += start + "," + end + ",";
        else
            result += start + "-" + end + ",";

        start = end = arr[i];
    }
}

// handle the final group
if (start == end)
    result += start;
else
    result += start + "-" + end;

Demo: http://ideone.com/7HdpS7


A little bit of LINQ will tidy this up:

static IEnumerable<Tuple<int, int>> GetRanges(IEnumerable<int> source)
{
   bool started = false;
   int rangeStart = 0, lastItem = 0;

   foreach (int item in source)
   {
      if (!started)
      {
         rangeStart = lastItem = item;
         started = true;
      }
      else if (item == lastItem + 1)
      {
         lastItem = item;
      }
      else
      {
         yield return new Tuple<int, int>(rangeStart, lastItem);
         rangeStart = lastItem = item;
      }
   }

   if (started)
   {
      yield return new Tuple<int, int>(rangeStart, lastItem);
   }
}

static string FormatRange(Tuple<int, int> range)
{
   string format = (range.Item1 == range.Item2) ? "{0:D}" : "{0:D}-{1:D}";
   return string.Format(format, range.Item1, range.Item2);
}

string pageNos = "5,6,7,9,10,11,12,15,16";
int[] pageNumbers = Array.ConvertAll(pageNos.Split(','), Convert.ToInt32);
string result = string.Join(",", GetRanges(pageNumbers).Select(FormatRange));

string pageNos = "5,6,7,9,10,11,12,15,16";
string[] arr1 = pageNos.Split(',');
int[] arr = new int[arr1.Length];

for (int x = 0; x < arr1.Length; x++) // Convert string array to integer array
{
    arr[x] = Convert.ToInt32(arr1[x]);
}

StringBuilder sb = new StringBuilder();
bool hyphenOpen = false;
for (int i = 0; i < arr.Length - 1; i++)
{
    if (arr[i] + 1 == arr[i+1])
    {
        if (!hyphenOpen)
        {
            hyphenOpen = true;
            sb.Append(arr[i] + "-");
        }
    }
    else
    {
        hyphenOpen = false;
        sb.Append(arr[i] + ",");
    }
}
sb.Append(arr[arr.Length-1]);
Console.WriteLine(sb.ToString());

This is long and clunky, but it works.

P.S. - I left the OP's original string->int as is, see comment by JonB on question for much cleaner method.

Tags:

C#

Algorithm