如何统计嵌套L1标签内元素总数?C#代码问题排查与优化
问题
我需要统计一段包含嵌套<L1>标签的列表字符串中,每个<L1>标签内的元素总数。示例结构如下:
<L1 //2 element <L1 //1 element <H1 content> > <L1 //3 element <H2 content> <P content> <L1 //1 element <H3 content> > > >
我写了一段C#代码,但运行结果不符合预期:
var str = "<L1 <L1 <H1 content> > <L1 <H2 content> <P content> <L1 <H3 content> > > >"; var list = str.Split(new string[] { "\n" }, StringSplitOptions.None); var array_num = new List<string>(); int startpos = 0, endpos = 0, total = 0, newstartpos = 0; bool newtag = false; for (int i = 0; i < list.Length; i++) { if (list[i].Trim() == "<L1") { startpos = i; for (int Lindex = i + 1; Lindex < list.Length ; Lindex++) { var item = list[Lindex].Trim().ToString(); if (list[Lindex].Trim().StartsWith("<L1") && list[Lindex].Trim().EndsWith(">")) { total += 1; } if (list[Lindex].Trim() == "<L1") { total += 2; newstartpos = Lindex; newtag = true; } if (list[Lindex].Trim() == ">" && newstartpos != 0) { total -= 1; endpos = Lindex; newtag = false; } if (list[Lindex].Trim().StartsWith("<") && list[Lindex].Trim().EndsWith(">") && !newtag) { total += 1; } if (list[Lindex].Trim() == ">" && newstartpos == 0) { endpos = Lindex; break; } } array_num.Add("start: " + startpos + " end: " + endpos + " count: " + total); startpos = 0; endpos = 0; total = 0; newstartpos = 0; newtag = false; } }
正确结果应该是:
start:0 end: 11 count: 2 //correct start:1 end: 3 count: 1 //correct start:4 end: 10 count: 3 //原结果错误 start:7 end: 9 count: 1 //correct
原代码在部分案例下统计错误,也不确定稳定性,需要调整方案或优化建议。
代码调整方案
嵌套标签的统计适合用栈结构处理,能精准匹配<L1>的开始和结束标签,避免嵌套逻辑混乱。以下是优化后的代码:
var str = "<L1 <L1 <H1 content> > <L1 <H2 content> <P content> <L1 <H3 content> > > >"; var lines = str.Split(new[] { "\n" }, StringSplitOptions.None); var result = new List<string>(); var stack = new Stack<(int startLine, int elementCount)>(); for (int lineIndex = 0; lineIndex < lines.Length; lineIndex++) { var trimmedLine = lines[lineIndex].Trim(); if (trimmedLine == "<L1") { // 遇到新的L1标签,压入栈记录起始行和初始计数 stack.Push((lineIndex, 0)); } else if (trimmedLine == ">") { // 遇到结束标签,弹出栈顶的L1记录 if (stack.Count > 0) { var currentL1 = stack.Pop(); int endLine = lineIndex; int count = currentL1.elementCount; // 如果栈不为空,当前L1是父L1的子元素,父元素计数+1 if (stack.Count > 0) { var parent = stack.Pop(); stack.Push((parent.startLine, parent.elementCount + 1)); } result.Add($"start: {currentL1.startLine} end: {endLine} count: {count}"); } } else if (trimmedLine.StartsWith("<") && trimmedLine.EndsWith(">") && !trimmedLine.StartsWith("<L1")) { // 遇到普通元素,给栈顶的L1计数+1 if (stack.Count > 0) { var current = stack.Pop(); stack.Push((current.startLine, current.elementCount + 1)); } } } // 输出结果(若需要从外层到内层,可反转result) foreach (var item in result.AsEnumerable().Reverse()) { Console.WriteLine(item); }
核心思路
- 栈结构匹配嵌套:每个
<L1>入栈,遇到>出栈,完美对应嵌套层级,不会出现层级判断错误。 - 精准计数逻辑:
- 普通元素(如
<H1>、<P>)直接给当前栈顶的<L1>计数+1。 - 子
<L1>作为父<L1>的一个元素,子<L1>结束时,父<L1>计数+1。
- 普通元素(如
- 简化状态管理:去掉原代码中复杂的
newtag、newstartpos等状态变量,逻辑更清晰,稳定性更高。
运行这段代码后,会输出符合预期的顺序结果:
start: 0 end: 11 count: 2 start: 1 end: 3 count: 1 start: 4 end: 10 count: 3 start: 7 end: 9 count: 1
内容的提问来源于stack exchange,提问作者Headshot
相关产品推荐
相关产品推荐

