【问题标题】:Replace (invert) opening and closing brackets in one pass一次替换(反转)打开和关闭括号
【发布时间】:2015-04-21 11:14:24
【问题描述】:

解决方案应该很简单,但仍在苦苦挣扎。如何反转括号、圆括号、大括号等分组符号...

我的字符串是这样的:Lorem ipsum dolor )sit amet(, consectetur ]adipiscing[ elit

我想输出为Lorem ipsum dolor (sit amet), consectetur [adipiscing] elit

关键是如果我在多次传递中逐个符号转换,它会被转换两次:

text = text.Replace('[', ']');
text = text.Replace(']', '[');
text = text.Replace('(', ')');
text = text.Replace(')', '(');

结果是Lorem ipsum dolor (sit amet(, consectetur [adipiscing[ elit

如何一次性转换文本?

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    像古人那样做……你逐个字符地重建字符串……

    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();
    

    或者你可以开始你的混淆 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());
    

    【讨论】:

      【解决方案2】:

      我会使用StringBuilder 方法:

      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();
      }
      

      测试:

      string newStr = SwapGroupingSymbols("Lorem ipsum dolor )sit amet(, consectetur ]adipiscing[ elit");
      // Lorem ipsum dolor (sit amet), consectetur [adipiscing] elit
      

      【讨论】:

        【解决方案3】:

        让我也添加一个正则表达式选项:

        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 "[";
                }  
            }
        

        【讨论】:

          【解决方案4】:

          字符串是可以用 LINQ 处理的序列:

          text = new string(text.Select(c =>
           c == '[' ? ']' :
           c == ']' ? '[' :
           ...
           c).ToArray());
          

          这会很慢。处理每个字符的手动循环会快得多。

          【讨论】:

            【解决方案5】:

            这是最古老的解决方法,只使用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@@", ")");
            

            输出:

            【讨论】:

            • 如果你真的想这样做,你可以/应该至少使用私有区域 unicode 字符 :-) 或者至少是非字母字符。
            • @xanatos:我同意,我们通常使用 @@csbr@@ 之类的东西来避免问题。
            【解决方案6】:

            对于不同的括号,我会在两次传递中使用正则表达式。

            string newStr = "Lorem ipsum dolor )sit amet(, consectetur ]adipiscing[ elit";
            var newx = Regex.Replace(newStr, "(\\))(.*)(\\()", "($2)");
            var newy = Regex.Replace(newx, "(\\])(.*)(\\[)", "[$2]");
            newy.Dump();
            

            这会产生。在 Linqpad 上测试。

            Lorem ipsum dolor (sit amet), consectetur [adipiscing] 精英

            【讨论】:

            • 只有在输入字符串中的括号格式正确时才会起作用。它不会反转“错位”的括号。
            【解决方案7】:
            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());
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-01-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多