在括号中用嵌套子项拆分逗号分隔的字符串

时间:2016-03-03 20:27:54

标签: c# regex

我的字符串格式如下:" 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. a
  2. b
    2.1。 ç
    2.2。 d
    2.2.1。 Ë
    2.2.2。 ˚F
    2.3。 g
  3. h

  4. 4.1。 Ĵ
    4.2。 ķ
    4.2。升
  5. 最有效的方法是什么?

3 个答案:

答案 0 :(得分:1)

你可以像这样使用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>();
    }
}

答案 1 :(得分: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,..)更改为单词(方舟,书,...)):

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

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

答案 2 :(得分:1)

如果您不在乎不平衡括号类型:

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