Reputation: 845
The solution should be simple, but still struggling. How can I invert grouping symbols like brackets, parenthesizes, braces, ...
My string is like : Lorem ipsum dolor )sit amet(, consectetur ]adipiscing[ elit
I want output as Lorem ipsum dolor (sit amet), consectetur [adipiscing] elit
The point is if I transform symbol by symbol in multiple passes, it is transformed twice :
text = text.Replace('[', ']');
text = text.Replace(']', '[');
text = text.Replace('(', ')');
text = text.Replace(')', '(');
And the result is Lorem ipsum dolor (sit amet(, consectetur [adipiscing[ elit
How can I transform the text in one pass ?
Upvotes: 2
Views: 802
Reputation: 101
const string input = @"Lorem ipsum dolor )sit amet(, consectetur ]adipiscing[ elit";
Dictionary<char, char> dic = new Dictionary<char, char> { { '[', ']' }, { ']', '[' }, { '(', ')' }, { ')', '(' } };
string output = new String(input.Select(n => dic.ContainsKey(n) ? dic[n] : n).ToArray());
Upvotes: 0
Reputation: 5199
I would use regex in two passes for different parenthesis.
string newStr = "Lorem ipsum dolor )sit amet(, consectetur ]adipiscing[ elit";
var newx = Regex.Replace(newStr, "(\\))(.*)(\\()", "($2)");
var newy = Regex.Replace(newx, "(\\])(.*)(\\[)", "[$2]");
newy.Dump();
This would produce. Tested on Linqpad.
Lorem ipsum dolor (sit amet), consectetur [adipiscing] elit
Upvotes: 0
Reputation: 111890
Do as the ancients would have done... You rebuild the string character by character...
string str = "Lorem ipsum dolor )sit amet(, consectetur ]adipiscing[ elit";
var sb = new StringBuilder(str.Length);
foreach (char ch in str)
{
switch (ch)
{
case '[':
sb.Append(']');
break;
case ']':
sb.Append('[');
break;
case '(':
sb.Append(')');
break;
case ')':
sb.Append('(');
break;
default:
sb.Append(ch);
break;
}
}
string str2 = sb.ToString();
Or you could begin your course of obfuscated C# :-)
string str3 = new Regex(@"[\[\]()]")
.Replace(str, x => ((char)(x.Value[0] + (x.Value == "[" || x.Value == "(" ?
1 + (x.Value[0] / '[') :
-1 - (x.Value[0] / '[')))).ToString());
Upvotes: 9
Reputation: 627082
And this is the oldest workaround just using String.Replace()
:
var st = "Lorem ipsum dolor )sit amet(, consectetur ]adipiscing[ elit";
st = st.Replace("[", "@@osbr@@").Replace("]", "@@csbr@@").Replace(")", "@@crbr@@").Replace("(", "@@orbr@@");
st = st.Replace("@@osbr@@", "]").Replace("@@csbr@@", "[").Replace("@@crbr@@", "(").Replace("@@orbr@@", ")");
Output:
Upvotes: 0
Reputation: 82504
Let me just add a regular expression option as well:
string s = "Lorem ipsum dolor )sit amet(, consectetur ]adipiscing[ elit";
s = Regex.Replace(s, @"(\[)|(\])|(\()|(\))", new MatchEvaluator(InvertBrackets));
private string InvertBrackets(Match m)
{
switch(m.Value) {
case "(":
return ")";
case ")":
return "(";
case "[":
return "]";
default:
return "[";
}
}
Upvotes: 1
Reputation: 460208
I would use a StringBuilder
approach:
static readonly Dictionary<char, char> ReplacementChars = new Dictionary<char, char>
{
{ '[', ']'},{']', '['},{')', '('}, {'(', ')'}
};
public static string SwapGroupingSymbols(string str)
{
StringBuilder sb = new StringBuilder(str.Length);
foreach (char c in str)
{
char newChar;
bool contains = ReplacementChars.TryGetValue(c, out newChar);
sb.Append(contains ? newChar : c);
}
return sb.ToString();
}
Test:
string newStr = SwapGroupingSymbols("Lorem ipsum dolor )sit amet(, consectetur ]adipiscing[ elit");
// Lorem ipsum dolor (sit amet), consectetur [adipiscing] elit
Upvotes: 2
Reputation: 171206
A string is a sequence that can be processed with LINQ:
text = new string(text.Select(c =>
c == '[' ? ']' :
c == ']' ? '[' :
...
c).ToArray());
This is going to be slow. A manual loop that processes each char would be much faster.
Upvotes: 0