2016-03-03 85 views
2

我有一个格式如下所示的字符串:“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。 e
    2.2.2。 f
    2.3。 g
  3. h
  4. i
    4.1。 j
    4.2。 k
    4.2。 l

什么是最有效的方法呢?

+0

就性能而言,由于C#是一种编译语言,如果您编写自己的解析器(无正则表达式),您将获得最佳结果。 –

+2

您能否为此列表显示一个示例输出? –

+0

孩子的平面列表,还是基于parthentical结构嵌套? – lintmouse

回答

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

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

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

有趣的想法。我在我的问题上加了一个说明。这些字母代表结构,但每个字母可以是一个或多个字。我也需要维护订单。 – Loscas

+0

@Loscas,你能举一个这样的输入的例子吗? –