Compress numbers in a string array (#3, #1, #2, #4) to range (#1:#4)
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);
}