【问题标题】:c# sorting data from an adjacency treec# 对邻接树中的数据进行排序
【发布时间】:2013-06-28 13:58:03
【问题描述】:

我有一堆数据将被表示为一棵树。我正在使用的控件需要正确排序数据。

这是每个节点的结构:

public class TreeNode
{
    public Guid id { get; set; }
    public string name { get; set; }
    public int level { get; set; }
    public Guid? parent { get; set; }
    public bool isLeaf { get; set; }    
}

我需要一种对数据进行排序的方法,以便我有一个 TreeNodes 列表,首先是根,然后是它的子节点,依此类推。换句话说,所有直接孩子都需要跟随列表中的父母。

我还希望按名称对子节点和叶节点进行排序。 (> = 可扩展,o = 叶)

root >
  level1a >         
  level1b >
     level2d >
     level2a o
  level1a o
  level1b o

有没有简单的方法可以做到这一点?

我假设我需要一些递归函数,并且无法使用 order by 语句的组合对其进行排序(类似于list.OrderBy(x => x.parent).ThenBy(x => x.level).ThenBy(x => x.isLeaf);

【问题讨论】:

    标签: c# recursion jqgrid tree


    【解决方案1】:

    您说得对,使用单个 LINQ 表达式执行此操作并不简单。这种递归方法应该可以解决问题:

    IEnumerable<TreeNode> TreeOrder(
        IEnumerable<TreeNode> nodes)
    {
        //Find the root node
        var root = nodes.Single(node => node.parent == null);
    
        //Build an inverse lookup from parent id to children ids
        var childrenLookup = nodes
            .Where(node => node.parent != null)
            .ToLookup(node => node.parent.Value);
    
        return TreeOrder(root, childrenLookup);
    }
    
    IEnumerable<TreeNode> TreeOrder(
        TreeNode root,
        ILookup<Guid, TreeNode> childrenLookup)
    {
        yield return root;
    
        if (!childrenLookup.Contains(root.id))
            yield break;
    
        foreach (var child in childrenLookup[root.id])
            foreach (var node in TreeOrder(child, childrenLookup))
                yield return node;
    }
    

    【讨论】:

    • 您可以将输入数据与目录和文件进行比较。 isLeaf 属性表示:“是文件吗?”。该顺序应对应按名称排序的董事树的扩展顺序。列表中的拳头应为“A”。列表中的最后一个应该是“A”的“文件”(具有isLeaf === true 的项目)。如果所有项目都是“目录”,那么正确的顺序应该是“ABDECFG”。如果一个目录同时包含子目录 文件,则应首先列出子目录,然后列出文件。
    • @Timothy: Oleg 说了什么 :) ABDECFG
    • @Timothy,不会编译:foreach (var node in TreeOrder(childrenLookup[root.id]) TreeOrder 没有重载需要 1 个参数。我还将.Where(node.parent.HasValue) 更改为.Where(node =&gt; node.parent.HasValue)
    • @Timothy,还没到那里...childrenLookup[root.id] 返回一个 IEnumerable...我应该只接受childrenLookup[root.id].First() 吗?令人印象深刻的浏览器代码:)
    • childrenLookup[root.id] 返回一个IEnumerable&lt;TreeNode&gt;。这就是为什么它在外部foreach 循环中被用作IEnumerable&lt;TreeNode&gt;。也许您正在查看我编辑之前的以前的版本,我仍然有错误?
    猜你喜欢
    • 1970-01-01
    • 2013-03-08
    • 1970-01-01
    • 1970-01-01
    • 2020-08-23
    • 1970-01-01
    • 2011-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多