[英]Clean fastest & efficient way to parse a string in c#
我必须在 C# 中创建一个字符串解析器。 字符串需要在父子关系中解析,字符串如下:
Water, Bulgur Wheat (29%), Sweetened Dried Cranberries (5%) (Sugar, Cranberries), Sunflower Seeds (3%), Onion (3%), Green Lentils (2%), Palm Oil, Flavourings (contain Barley), Lemon Juice Powder (<2%) (Maltodextrin, Lemon Juice Concentrate), Ground Spices (<2%) (Paprika, Black Pepper, Cinnamon, Coriander, Cumin, Chilli Powder, Cardamom, Pimento, Ginger), Dried Herbs (<2%) (Coriander, Parsley, Mint), Dried Garlic (<2%), Salt, Maltodextrin, Onion Powder (<2%), Cumin Seeds, Dried Lemon Peel (<2%), Acid (Citric Acid)
我知道我可以逐个字符地查找并最终找到通过它的方式,但是获取此信息的最简单方法是什么。
预期输出:-
public static string ParseString(string input)
{
StringBuilder sb = new StringBuilder();
bool skipNext = false; // used to skip spaces after commas
foreach (char c in input)
{
if (!skipNext)
{
switch (c)
{
case '(':
sb.Append("\n\t");
break;
case ',':
sb.Append("\n");
skipNext = true;
break;
case ')':
sb.Append("\n");
break;
default:
sb.Append(c);
break;
}
}
else
{
skipNext = false;
}
}
return sb.ToString();
}
这应该让你开始。 它不处理不表示孩子的括号。
在查看发布的数据(水,保加利亚……)后,一个问题将区分/分离每个单独的项目:1 水,2 保加利亚……,3 加糖。
拆分逗号“,”将不起作用,因为某些括号“()”内有逗号,如 (Sugar, Cranberries)。 这些项目(糖、蔓越莓)是甜蔓越莓干的子项目......所以用逗号分割字符串是行不通的。
根据您给定的数据,我会考虑更改其格式以适应这种情况。 一个简单的更改是将子组之间的逗号分隔符更改为其他内容……破折号“-”可能会起作用。
下面的正则表达式代码就是这样做的。 这基本上将每个逗号“,”在左括号和右括号“()”之间更改为破折号“-”。 这将允许用逗号分隔来标识每个项目。
private static string ReplaceCommaBetweenParens(string inString) {
string pattern = @"(?<=\([^\)]*)+,(?!\()(?=[^\(]*\))";
return Regex.Replace(inString, pattern, "-");
}
上面的代码并不漂亮,我从其他地方得到了这段代码,希望能找到原作者的网站。 我欢迎所有正则表达式爱好者批评该模式。 我不确定您将如何使用常规字符串方法(split/indexof)来完成此操作。 我相信这需要几个步骤。 正则表达式在某些情况下是多么有用的一个很好的例子。 它可能很丑,但它的工作速度非常快。 幸运的是,在这一步之后,上面的神秘代码 (Regex) 不会有太大帮助。
进行此更改后,根据需要缩进输出是一个相当简单的过程。 下面的代码从DataTable
读取每一行。 每行可能有 1 个或多个项目,用逗号“,”隔开。 代码遍历每一行,解析字符串中的项目。 我做了一个简单的类来保存物品; 但是,如果不需要类,代码会带有正确的输出。 希望这可以帮助。
保存单个项目的简单类
class Ingredient {
int ID { get; set; }
string Name { get; set; }
string Percent { get; set; }
List<string> Ingredients { get; set; }
public Ingredient(int id, string name, string pct, List<string> ingredients) {
ID = id;
Name = name;
Percent = pct;
Ingredients = ingredients;
}
public override string ToString() {
StringBuilder sb = new StringBuilder();
sb.Append(ID + "\t" + Name + " " + Percent + Environment.NewLine);
foreach (string s in Ingredients) {
sb.Append("\t\t" + s + Environment.NewLine);
}
return sb.ToString();
}
}
使用上述类的代码
static string ingredients = "Water, Bulgur Wheat(29%), Sweetened Dried Cranberries(5%) (Sugar, Cranberries)," +
" Sunflower Seeds(3%), Onion(3%), Green Lentils(2%), Palm Oil, Flavourings (contain Barley)," +
" Lemon Juice Powder(<2%) (Maltodextrin, Lemon Juice Concentrate)," +
" Ground Spices(<2%) (Paprika, Black Pepper, Cinnamon, Coriander, Cumin, Chilli Powder, Cardamom, Pimento, Ginger)," +
" Dried Herbs(<2%) (Coriander, Parsley, Mint), Dried Garlic(<2%), Salt, Maltodextrin, Onion Powder(<2%)," +
" Cumin Seeds, Dried Lemon Peel(<2%), Acid(Citric Acid)";
static List<Ingredient> allIngredients;
static void Main(string[] args) {
allIngredients = ParseString(ingredients);
foreach (Ingredient curIngredient in allIngredients) {
Console.Write(curIngredient.ToString());
}
Console.ReadLine();
}
private static List<Ingredient> ParseString(string inString) {
List<Ingredient> allIngredients = new List<Ingredient>();
string temp = ReplaceCommaBetweenParens(ingredients);
string[] allItems = temp.Split(',');
int count = 1;
foreach (string curItem in allItems) {
if (curItem.Contains("(")) {
allIngredients.Add(ParseItem(curItem, count));
}
else {
allIngredients.Add(new Ingredient(count, curItem.Trim(), "", new List<string>()));
//Console.WriteLine(count + "\t" + curItem.Trim());
}
count++;
}
return allIngredients;
}
private static Ingredient ParseItem(string item, int count) {
string pct = "";
List<string> items = new List<string>();
int firstParenIndex = item.IndexOf("(");
//Console.Write(count + "\t" + item.Substring(0, firstParenIndex).Trim());
Regex expression = new Regex(@"\((.*?)\)");
MatchCollection matches = expression.Matches(item);
bool percentPresent = true;
foreach (Match match in matches) {
if (match.ToString().Contains("%")) { // <-- if the string between parenthesis does not contain "%" - move to next line, otherwise print on same line
//Console.WriteLine(" " + match.ToString().Trim());
pct = match.ToString().Trim();
percentPresent = false;
}
else {
if (percentPresent) {
//Console.WriteLine();
}
items = GetLastItems(match.ToString().Trim());
}
}
return new Ingredient(count, item.Substring(0, firstParenIndex).Trim(), pct, items);
}
private static List<string> GetLastItems(string inString) {
List<string> result = new List<string>();
string temp = inString.Replace("(", "");
temp = temp.Replace(")", "");
string[] allItems = temp.Split('-');
foreach (string curItem in allItems) {
//Console.WriteLine("\t\t" + curItem.Trim());
result.Add(curItem.Trim());
}
return result;
}
private static string ReplaceCommaBetweenParens(string inString) {
string pattern = @"(?<=\([^\)]*)+,(?!\()(?=[^\(]*\))";
return Regex.Replace(inString, pattern, "-");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.