gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 23:23:21 25 4
gpt4 key购买 nike

我有一个包含 4 列的数据集。名称、 key 、parentKey、级别。我需要将此 DataTable 转换为树结构。我附上了一张图片,可以让您了解我想做什么。将 DataTable 转换为可用于生成树结构的对象的最有效方法是什么。请帮忙。

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

enter image description here

我已经添加了一个模拟数据集的类并且我已经对数据表中的数据进行了排序。

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", "A1", 2);
table.Rows.Add("C", "A3", "A1", 2);
table.Rows.Add("D", "A4", "A1", 2);

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


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

table.Rows.Add("M", "A13", "A12", 5);
table.Rows.Add("N", "A14", "A12", 5);
table.Rows.Add("O", "A15", "A10", 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, Func<T, 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, Func<T, bool> startWith, Func<T, T, 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), connectBy, 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,
Func<T, bool> startWith,
Func<T, 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>(
this IEnumerable<T> source,
Func<T, bool> startWith,
Func<T, T, 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), connectBy, newNode));

yield return newNode;
}
}

如果是 DataTable作为来源,您可以像这样使用它:

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

( hierarchy 是一个 IEnumerable<Node<DataRow>> )

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

关于c# - 使用C#将数据表的结果转换为树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18203851/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com