【问题标题】:Split a comma delimited string with nested children in parentheses用括号中的嵌套子级拆分逗号分隔的字符串
【发布时间】:2020-09-14 23:37:46
【问题描述】:

我有一个格式如下的字符串:“a, b(c,d(e,f),g),h, i(j, k, l)" 其中每个字母代表一个或多个单词。

我需要将此字符串拆分为对象列表:

public class Item
{
    public string Name { get; set; }
    public IEnumerable<Item> Children { get; set; }

    public Ingredient()
    {
        Children = new List<Item>();
    }
}

以大纲格式表示的期望结果:

  1. 一个
  2. b
    2.1。 c
    2.2. d
    2.2.1。电子
    2.2.2。 f
    2.3. g
  3. h

  4. 4.1。 j
    4.2. k
    4.2. l

这样做最有效的方法是什么?

【问题讨论】:

  • 在性能方面,由于C#是一种编译语言,如果你自己写解析器(不带正则表达式),你会得到最好的结果。
  • 能否请您显示此列表的示例输出?
  • 一个平面的子列表,还是基于parthentical结构嵌套?
  • 基于括号结构嵌套。我更新了试图说明这一点,但我的格式不断丢失。

标签: c# regex


【解决方案1】:

你可以像这样使用递归算法来解析你的字符串:

static IEnumerable<Item> Parse(string source)
{
    var root = new Item() { Name = "Root", Children = new List<Item>() };
    AddChildrenTo(root, source);
    return root.Children;
}

static int AddChildrenTo(Item item, string source)
{
    Item node = null;
    var word = new List<char>();
    for (int i = 0; i < source.Length; i++)
    {
        var c = source[i];
        if (new[] { ',', '(', ')' }.Contains(c))
        {
            if (word.Count > 0)
            {
                node = new Item { Name = new string(word.ToArray()), Children = new List<Item>() };
                (item.Children as List<Item>).Add(node);
                word.Clear();
            }

            if (c == '(')
            {
                i += AddChildrenTo(node, source.Substring(i + 1)) + 1;
            }
            else if (c == ')')
            {
                return i;
            }
        }
        else if (char.IsLetter(c)) // add other valid characters to if condition 
        {
            word.Add(c);
        }
    }

    return source.Length;
}

然后您可以简单地调用Parse()(为了更好地演示,我已将字符串中的字母(a,b,..)更改为单词(ark,book,...)):

string source = "ark,book(cook,door(euro,fun),good),hello,ink(jack,kill,loop)";
var res = Parse(source);

请注意,对于非常大的字符串递归方法不是最好的解决方案。为简单起见,我没有进行错误检查。

【讨论】:

    【解决方案2】:

    您可以像这样使用stack

    static public List<Item> Parse(string str)
    {
        Stack<Item> stack = new Stack<Item>();
    
        Item root = new Item();
    
        stack.Push(root);
    
        foreach (char c in str)
        {
            if (char.IsLetter(c))
            {
                Item item = new Item();
    
                item.Name = c.ToString();
    
                stack.Peek().Children.Add(item);
    
                stack.Push(item);
            }
            else if (c == ')' || c == ',')
            {
                stack.Pop();
            }
        }
    
        return root.Children;
    }
    

    请注意,Children 属性必须是 List,如下所示:

    public class Item
    {
        public string Name { get; set; }
        public List<Item> Children { get; set; }
    
        public Item()
        {
            Children = new List<Item>();
        }
    }
    

    【讨论】:

    • 有趣的想法。我对我的问题进行了澄清。字母代表结构,但每个都可以是一个或多个单词。我也需要维持秩序。
    • @Loscas,你能举个例子吗?
    【解决方案3】:

    如果你不关心不平衡括号类型:

    static string[] SplitString(string input)
    {
        bool nSingleQuote = false;
        bool nDubbleQuote = false;
    
        int nBracket = 0;
        int start = 0;
        List<String> result = new List<String>();
        for (int i = 0; i < input.Length; i++)
        {
            char c = input[i];
            if (c == '\'')
            {
                if(!nDubbleQuote) nSingleQuote = !nSingleQuote;
            }
            else if (c == '"')
            {
                if(!nSingleQuote) nDubbleQuote = !nDubbleQuote;
            }
    
            if (!nSingleQuote && !nDubbleQuote)
            {
                if (c == ',')
                {
                    if (nBracket == 0)
                    {
                        result.Add(input.Substring(start, i - start).Trim());
                        start = i + 1;
                    }
                }
                else if (c == '(' || c == '[' || c == '{')
                {
                    nBracket++;
                }
                else if (c == ')' || c == ']' || c == '}')
                {
                    nBracket--;
                    if (nBracket < 0)
                        throw new Exception("Unbalanced parenthesis, square bracket or curly bracket at offset #" + i);
                }
            }
        }
        if (nBracket > 0)
            throw new Exception("Missing closing parenthesis, square bracket or curly bracket");
        if (nSingleQuote || nDubbleQuote)
            throw new Exception("Missing end quotation mark");
        result.Add(input.Substring(start).Trim());
        return result.ToArray();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-07
      • 2018-12-21
      • 1970-01-01
      • 2017-01-05
      • 2010-11-08
      • 1970-01-01
      相关资源
      最近更新 更多