加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

使用C#将数据表的结果转换为树

发布时间:2020-12-15 05:41:05 所属栏目:百科 来源:网络整理
导读:我有一个包含4列的数据集.名称,密钥,parentKey,级别.我需要将此DataTable转换为树结构.我附上一张图片,可以让你知道我想做什么.将DataTable转换为可用于生成树结构的对象的最有效方法是什么.请帮忙. 请注意:数据可以在DataTable中以任何顺序出现.是否可以在
我有一个包含4列的数据集.名称,密钥,parentKey,级别.我需要将此DataTable转换为树结构.我附上一张图片,可以让你知道我想做什么.将DataTable转换为可用于生成树结构的对象的最有效方法是什么.请帮忙.

请注意:数据可以在DataTable中以任何顺序出现.是否可以在第一级列上然后在parentKey列上对dataTable进行排序?我想,如果我能做到这一点,将输出转换为树结构会很容易.

我添加了一个模仿数据集的类.我已经在数据表中对数据进行了排序.

namespace SortDataTable
{


    public class Program
    {
        private static void Main(string[] args)
        {
            DataTable table = new DataTable();
            table.Columns.Add("Name",typeof (string));
            table.Columns.Add("Key",typeof (string));
            table.Columns.Add("ParentKey",typeof (string));
            table.Columns.Add("Level",typeof (int));


            table.Rows.Add("A","A1",null,1);
            table.Rows.Add("B","A2",2);
            table.Rows.Add("C","A3",2);
            table.Rows.Add("D","A4",2);

            table.Rows.Add("E","A5",3);
            table.Rows.Add("F","A6",4);
            table.Rows.Add("G","A7",3);
            table.Rows.Add("H","A8",3);


            table.Rows.Add("I","A9",3);
            table.Rows.Add("J","A10",3);
            table.Rows.Add("K","A11",4);
            table.Rows.Add("L","A12",4);

            table.Rows.Add("M","A13",5);
            table.Rows.Add("N","A14",5);
            table.Rows.Add("O","A15",4);

            DataView view = table.DefaultView;

            // By default,the first column sorted ascending.
            view.Sort = "Level,ParentKey DESC";


            foreach (DataRowView row in view)
            {
                Console.WriteLine(" {0} t {1} t {2} t {3}",row["Name"],row["Key"],row["ParentKey"],row["Level"]);
            }
            Console.ReadKey();

        }

    }


   public class Node<T>
    {
        internal Node() { }
        public T Item { get; internal set; }
        public int Level { get; internal set; }
        public Node<T> Parent { get; internal set; }
        public IList<Node<T>> Children { get; internal set; }



        public static IEnumerable<Node<T>> ToHierarchy<T>( IEnumerable<T> source,Func<T,bool> startWith,T,bool> connectBy)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (startWith == null) throw new ArgumentNullException("startWith");
            if (connectBy == null) throw new ArgumentNullException("connectBy");
            return source.ToHierarchy(startWith,connectBy,null);
        }

        private static IEnumerable<Node<T>> ToHierarchy<T>(IEnumerable<T> source,bool> connectBy,Node<T> parent)
        {
            int level = (parent == null ? 0 : parent.Level + 1);

            var roots = from item in source
                        where startWith(item)
                        select item;
            foreach (T value in roots)
            {
                var children = new List<Node<T>>();
                var newNode = new Node<T>
                {
                    Level = level,Parent = parent,Item = value,Children = children.AsReadOnly()
                };

                T tmpValue = value;
                children.AddRange(source.ToHierarchy(possibleSub => connectBy(tmpValue,possibleSub),newNode));

                yield return newNode;
            }
        }
    }





}

解决方法

我使用以下扩展方法来做这种事情:
public class Node<T>
    {
        internal Node() { }
        public T Item { get; internal set; }
        public int Level { get; internal set; }
        public Node<T> Parent { get; internal set; }
        public IList<Node<T>> Children { get; internal set; }
    }

    public static IEnumerable<Node<T>> ToHierarchy<T>(
        this IEnumerable<T> source,bool> connectBy)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (startWith == null) throw new ArgumentNullException("startWith");
        if (connectBy == null) throw new ArgumentNullException("connectBy");
        return source.ToHierarchy(startWith,null);
    }

    private static IEnumerable<Node<T>> ToHierarchy<T>(
        this IEnumerable<T> source,Node<T> parent)
    {
        int level = (parent == null ? 0 : parent.Level + 1);

        var roots = from item in source
                    where startWith(item)
                    select item;
        foreach (T value in roots)
        {
            var children = new List<Node<T>>();
            var newNode = new Node<T>
            {
                Level = level,Children = children.AsReadOnly()
            };

            T tmpValue = value;
            children.AddRange(source.ToHierarchy(possibleSub => connectBy(tmpValue,newNode));

            yield return newNode;
        }
    }

在DataTable作为源的情况下,您可以像这样使用它:

var hierarchy =
    sourceTable.AsEnumerable()
               .ToHierarchy(row => row.IsNull("ParentKey"),(parent,child) => parent.Field<int>("Key") ==
                                               child.Field<int>("ParentKey"))

(层次结构是IEnumerable< Node< DataRow>>)

请注意,如果在DataTable本身中定义父子关系,则您已经有了树结构……您只需选择根(没有父项的项).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读