Compress numbers in a string array (#3, #1, #2, #4) to range (#1:#4) This function takes a string array,

{"foo", "#123", "#124", "bar", "#125", "#126"}


makes a new array with the numbers converted to a range:

{"foo", "#123:126", "bar"}


and returns:

"foo,#123:126,bar"


Note it doesn't and shouldn't change {"#1", "#2"} to {"#1:#2"}



using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
    static void Main(string[] args)
    {
        var ids = new string[] {
            "foo", //output: unmodified
            "#60", "#59", "#61", "#62", //from integer is in between, output: #59:#62
            "#12", "#14", "#17", "#13", "#18", "#bar", "#19", "#20", //two ranges and string intertwined, output: #12:#14,#17:#20,#bar
            "#25", "#26", //output: unmodified
            "#39", "#38", //output: unmodified
            "baz", //output: unmodified
            "#12", "#13", "#14" //duplicate sequences, output: #12:#14
        };
        Console.WriteLine("foo,#59:#62,#12:#14,#17:#20,#bar,#25,#26,#38,#39,baz,#12:#14");
        Console.WriteLine(Compress(ids));
        Console.Read();
    }
    static string Compress(IEnumerable&lt;string&gt; IDs)
    {
        var result = new List&lt;string&gt;();
        var ignore = new HashSet&lt;string&gt;();
        foreach (var item in IDs)
        {
            if (ignore.Contains(item)) continue;
            var id = item;
            if (id.StartsWith("#"))
            {
                int fromInt;
                if (int.TryParse(id.Substring(1), out fromInt))
                {
                    var less1 = $"#{fromInt - 1}";
                    var plus1 = $"#{fromInt + 1}";
                    var hasPlus1 = IDs.Contains(plus1);
                    if (IDs.Contains(less1) &amp;&amp; hasPlus1) continue;
                    var plus2 = $"#{fromInt + 2}";
                    if (hasPlus1 &amp;&amp; IDs.Contains(plus2))
                    {
                        ignore.Add(plus1);
                        ignore.Add(plus2);
                        var toInt = fromInt + 2;
                        while (IDs.Contains($"#{toInt + 1}"))
                        {
                            toInt += 1;
                            ignore.Add($"#{toInt}");
                        }
                        id = $"#{fromInt}:#{toInt}";
                    }
                }
            }
            result.Add(id);
        }
        return string.Join(",", result);
    }
}
In addition to my answer on your other (related) post which is still valid here (with the proper modifications obviously) I'd suggest to use brackets even in case of if blocks with only 1 instructions. For example:

if (IDs.Contains(less1) &amp;&amp; hasPlus1) continue;


should become something like:

if (IDs.Contains(less1) &amp;&amp; hasPlus1)
{ 
    continue;
}


Also, var id = item; can be safely removed and you can work directly on item.

By applying all changes the method becomes something like the following:

static string Compress(IEnumerable&lt;string&gt; IDs)
{
    var result = new List&lt;string&gt;();
    var ignore = new HashSet&lt;string&gt;();
    foreach (var item in IDs)
    {
        if (ignore.Contains(item))
        { 
            continue;
        }
        if (!item.StartsWith("#"))
        {
            result.Add(item);
            continue;
        }
        int fromInt;
        if (!(int.TryParse(item.Substring(1), out fromInt)))
        {
            result.Add(item);
            continue;
        }
        var less1 = $"#{fromInt - 1}";
        var plus1 = $"#{fromInt + 1}";
        var hasPlus1 = IDs.Contains(plus1);
        if (IDs.Contains(less1) &amp;&amp; hasPlus1)
        { 
            continue;
        }
        var plus2 = $"#{fromInt + 2}";
        if (!(hasPlus1 &amp;&amp; IDs.Contains(plus2)))
        {
            result.Add(item);
            continue;
        }
        ignore.Add(plus1);
        ignore.Add(plus2);
        var toInt = fromInt + 2;
        while (IDs.Contains($"#{toInt + 1}"))
        {
            toInt += 1;
            ignore.Add($"#{toInt}");
        }
        result.Add($"#{fromInt}:#{toInt}");
    }
    return string.Join(",", result);
}