You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何遍历多层嵌套WorkItemClassificationNode集合?避免嵌套循环

这问题我之前处理树形嵌套结构的时候也碰到过!完全不用写一堆嵌套循环,递归或者迭代式的遍历(深度/广度优先)都是非常优雅的解决方案,给你具体拆解下怎么实现:

方法一:递归实现(最直观易写)

递归简直是为这种嵌套结构量身定做的——处理当前节点后,再递归处理它的所有子节点,逻辑清晰到一眼就能看懂。

举个C#的实现示例:

// 定义处理单个节点的逻辑方法
private void ProcessNode(WorkItemClassificationNode node)
{
    // 这里写你要对每个节点执行的逻辑,比如打印、修改属性等
    Console.WriteLine($"处理节点:{node.Name}");
}

// 递归遍历所有层级的方法
private void TraverseAllNodes(IEnumerable<WorkItemClassificationNode> nodes)
{
    if (nodes == null || !nodes.Any())
        return;

    foreach (var node in nodes)
    {
        // 先处理当前节点
        ProcessNode(node);
        // 再递归处理它的子节点
        TraverseAllNodes(node.Children);
    }
}

// 调用方式
TraverseAllNodes(items);

优点:代码极简,逻辑直观,几乎不用动脑子就能写出来。
小提醒:如果你的嵌套层级特别深(比如上千层),可能会触发栈溢出异常,但一般业务场景里这种情况很少见。

方法二:迭代式遍历(避免栈溢出风险)

要是担心递归的栈溢出问题,或者需要处理超深层级的结构,那迭代式的遍历就更稳妥了,核心是用集合(栈/队列)来模拟递归的调用栈。

2.1 深度优先遍历(用Stack)

和递归的遍历顺序一致,先深入到最底层的子节点,再回溯处理兄弟节点:

private void TraverseAllNodesDepthFirst(IEnumerable<WorkItemClassificationNode> rootNodes)
{
    if (rootNodes == null || !rootNodes.Any())
        return;

    var stack = new Stack<WorkItemClassificationNode>();
    // 先把根节点都压入栈,Reverse保证遍历顺序和递归一致
    foreach (var node in rootNodes.Reverse())
    {
        stack.Push(node);
    }

    while (stack.Count > 0)
    {
        var currentNode = stack.Pop();
        // 处理当前节点
        ProcessNode(currentNode);

        // 把子节点倒序压入栈,这样弹出的时候是正序
        if (currentNode.Children != null && currentNode.Children.Any())
        {
            foreach (var child in currentNode.Children.Reverse())
            {
                stack.Push(child);
            }
        }
    }
}

2.2 广度优先遍历(用Queue)

按层级从上到下遍历,先处理所有根节点,再处理第一层子节点,接着第二层,以此类推:

private void TraverseAllNodesBreadthFirst(IEnumerable<WorkItemClassificationNode> rootNodes)
{
    if (rootNodes == null || !rootNodes.Any())
        return;

    var queue = new Queue<WorkItemClassificationNode>();
    foreach (var node in rootNodes)
    {
        queue.Enqueue(node);
    }

    while (queue.Count > 0)
    {
        var currentNode = queue.Dequeue();
        // 处理当前节点
        ProcessNode(currentNode);

        // 把子节点依次入队
        if (currentNode.Children != null && currentNode.Children.Any())
        {
            foreach (var child in currentNode.Children)
            {
                queue.Enqueue(child);
            }
        }
    }
}
进阶:封装成可复用的扩展方法

如果需要多次用到这个遍历逻辑,还可以把扁平化的逻辑封装成扩展方法,这样用起来更丝滑:

public static class WorkItemExtensions
{
    // 深度优先扁平化所有节点
    public static IEnumerable<WorkItemClassificationNode> FlattenDepthFirst(this IEnumerable<WorkItemClassificationNode> nodes)
    {
        if (nodes == null) yield break;

        foreach (var node in nodes)
        {
            yield return node;
            // 递归扁平化子节点
            foreach (var child in node.Children.FlattenDepthFirst())
            {
                yield return child;
            }
        }
    }

    // 广度优先扁平化所有节点
    public static IEnumerable<WorkItemClassificationNode> FlattenBreadthFirst(this IEnumerable<WorkItemClassificationNode> nodes)
    {
        if (nodes == null) yield break;

        var queue = new Queue<WorkItemClassificationNode>(nodes);
        while (queue.Count > 0)
        {
            var node = queue.Dequeue();
            yield return node;
            if (node.Children != null)
            {
                foreach (var child in node.Children)
                {
                    queue.Enqueue(child);
                }
            }
        }
    }
}

// 调用方式超简单!
foreach (var node in items.FlattenDepthFirst())
{
    ProcessNode(node);
}

这样不管嵌套多少层,都能一行代码拿到所有节点,然后统一处理逻辑,完全不用写嵌套循环~

内容的提问来源于stack exchange,提问作者bdtrfs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:33:52