As I already wrote, you need a simple state machine (inside brackets, external brackets) ... Then for each character you analyze it, and if necessary, you change the state of the state machine and decide whether you need to output it or not.
public static string RemoveCommas(string str) { int bracketLevel = 0; var sb = new StringBuilder(str.Length); foreach (char ch in str) { switch (ch) { case '[': bracketLevel++; sb.Append(ch); break; case ']': if (bracketLevel > 0) { bracketLevel--; } sb.Append(ch); break; case ',': if (bracketLevel == 0) { sb.Append(ch); } break; default: sb.Append(ch); break; } } return sb.ToString(); }
Use it as:
string result = "a,b,c,[c,d,e],f,g,[h,i,j]"; Console.WriteLine(RemoveCommas(result));
Note that I use int to “save” the state of the state machine, so it works with recursive brackets, for example a,b,[c,d,[e,f]g,h]i,j
As an interesting exercise, this can be done with a slower LINQ expression:
string result2 = result.Aggregate(new { BracketLevel = 0, Result = string.Empty, }, (state, ch) => new { BracketLevel = ch == '[' ? state.BracketLevel + 1 : ch == ']' && state.BracketLevel > 0 ? state.BracketLevel - 1 : state.BracketLevel, Result = ch != ',' || state.BracketLevel == 0 ? state.Result + ch : state.Result }).Result;
At the end, the code is very similar ... There is a state that is taken ( BracketLevel ) plus a line ( Result ) that is being built. please do not use it , it is written only as a fun LINQ snippet.