首页 > 解决方案 > 用字符串括号内的分号替换逗号的最佳方法

问题描述

给定以下字符串:

string foo = "Foo, Bar, Baz (A, B, C), Fiz, Bang (Fiz, Bang)";

我想把它改成

Foo, Bar, Baz (A; B; C), Fiz, Bang (Fiz; Bang)

或者,如果我能以某种方式在 List 中以下列方式将其转换为字符串数组:

Foo
Bar
Baz (A, B, C)
Fiz
Bang (Fiz, Bang)

现在我正在做一个非常讨厌的方法,它有一个自定义的 foreach 并且感觉不干净或可扩展。当有更好的方法时,我觉得我正在努力做到这一点。

所以我呼吁hivemind寻求更好的解决方案。

编辑:

        public static void StuntForEachNext<T>(this IList<T> collection, Action<T, T, bool> func)
        {
            for (int i = 0; i < collection.Count - 1; i++)
            {
                func(collection[i], collection[i + 1], i == collection.Count - 2);
            }
        }
internal class Stunt_Parsed
        {
            public string MainStuntName { get; set; }
            public int StuntCount { get; set; }

            public List<string> Assigned_Associated_Stunts { get; set; } = new List<string>();

            public override string ToString()
            {
                return $"Stunt: {MainStuntName} x{StuntCount} ({Assigned_Associated_Stunts.Count})";
            }

            public static List<Stunt_Parsed> ParseStunts(string stunts)
            {
                List<Stunt_Parsed> returnStunts = new List<Stunt_Parsed>();

                bool isInParen = false;
                Stunt_Parsed newStunt = new Stunt_Parsed();

                stunts.Split(',').StuntForEachNext((stunt, nextStunt, isNextLast) =>
                {
                    string parsed_stunt = stunt;

                    if (stunt.Contains('('))
                    {
                        isInParen = true;
                        // Combine this one and the next one
                        string assoc_stunt = stunt + "," + nextStunt;
                        // Parse the things inside of the parentheses
                        int p1 = assoc_stunt.IndexOf('('); // 16
                        int p2 = assoc_stunt.Length;
                        if (assoc_stunt.Contains(')'))
                        {
                            p2 = assoc_stunt.IndexOf(')');
                            isInParen = false;
                        }

                        string s2 = assoc_stunt.Substring(p1 + 1, p2 - p1 - 1); // "Aura shield, dynamic shield, myfoo
                        string assoc_stunt1 = string.Empty;
                        string assoc_stunt2 = string.Empty;

                        foreach (string x in s2.Split(','))
                        {
                            string newString = x.Trim();
                            newStunt.Assigned_Associated_Stunts.Add(newString);
                        }

                        parsed_stunt = (parsed_stunt.Substring(0, parsed_stunt.Length - (parsed_stunt.Length - parsed_stunt.IndexOf('(')))).Trim(); // Spell Focus x2
                    }
                    else if (nextStunt.Contains(')') || isInParen)
                    {
                        // Already parsed
                        // Do nothing.
                        string newString = nextStunt.Replace(",", "").Replace(")", "").Trim();
                        newStunt.Assigned_Associated_Stunts.Add(newString);
                        if (nextStunt.Contains(')'))
                        {
                            returnStunts.Add(newStunt);
                            isInParen = false;
                            newStunt = new Stunt_Parsed();
                        }
                        return;
                    }
                    else if (stunt.Contains(')'))
                    {
                        return;
                    }

                    parsed_stunt = parsed_stunt.Trim();

                    if (parsed_stunt.ToLower().Contains(" x"))
                    {
                        int lastX = parsed_stunt.ToLower().LastIndexOf("x");
                        newStunt.StuntCount = int.Parse(parsed_stunt.Substring(lastX + 1, parsed_stunt.Length - lastX - 1));
                        newStunt.MainStuntName = parsed_stunt.Substring(0, lastX - 1);
                    }
                    else
                    {
                        newStunt.StuntCount = 1;
                        newStunt.MainStuntName = parsed_stunt;
                    }

                    if (!isInParen)
                    {
                        returnStunts.Add(newStunt);
                        newStunt = new Stunt_Parsed();
                    }
                });

                return returnStunts;
            }
        }

这段代码将不得不重新编写,因为我被告知括号中的内容可能比简单的昏迷更复杂,所以我决定暂时将它们存储在一个字符串中。

但是,我认为我可能会吸引更多的人,因为否则我只会做 ax += ", " nextStunt;直到右括号

标签: c#.net-core-3.1

解决方案


你可以试试有限状态机(FSM);它有foreach循环,我希望它很简单,而不是丑陋的:

  private static string Transform(string value) {
    if (string.IsNullOrEmpty(value))
      return value;

    StringBuilder sb = new StringBuilder(value.Length);

    int count = 0;

    foreach (char c in value) 
      if (c == ',') 
        sb.Append(count > 0 ? ';' : c);
      else {
        sb.Append(c);

        if (c == '(')
          count += 1;
        else if (c == ')')
          count -= 1;      
      }  

    return sb.ToString();  
  }

然后

  string result = Transform(foo);

推荐阅读