[英]Split a comma delimited string with nested children in parentheses
I have a string formatted something like this: "a, b(c,d(e,f),g),h, i(j, k, l)" where each letter represents one or more words.我有一个格式如下的字符串:“a, b(c,d(e,f),g),h, i(j, k, l)”,其中每个字母代表一个或多个单词。
I need to split this string up in to a list of objects:我需要将此字符串拆分为一个对象列表:
public class Item
{
public string Name { get; set; }
public IEnumerable<Item> Children { get; set; }
public Ingredient()
{
Children = new List<Item>();
}
}
The desired result represented in an outline format:以大纲格式表示的所需结果:
What would be the most efficient way to do so?这样做的最有效方法是什么?
You can use a stack like this:您可以使用这样的堆栈:
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;
}
Please note that the Children
property needs to be a List
like this:请注意, Children
属性需要是这样的List
:
public class Item
{
public string Name { get; set; }
public List<Item> Children { get; set; }
public Item()
{
Children = new List<Item>();
}
}
You can use a recursive algorithm to parse your string like this:您可以使用递归算法来解析您的字符串,如下所示:
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;
}
Then you can simply call Parse()
(For better demonstration I've changed the letters (a, b, ..) in your string to words (ark, book, ...)):然后你可以简单地调用Parse()
(为了更好的演示,我将字符串中的字母 (a, b, ..) 更改为单词 (ark, book, ...)):
string source = "ark,book(cook,door(euro,fun),good),hello,ink(jack,kill,loop)";
var res = Parse(source);
Please note that for a very large string recursive approach wouldn't be the best solution.请注意,对于非常大的字符串递归方法不是最好的解决方案。 And for simplicity I didn't do the error checkings.为简单起见,我没有进行错误检查。
If you don't care about unbalanced bracket type:如果您不关心不平衡的支架类型:
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();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.