读取通用列表<;T>;将父/子层次结构转换为保留父/子层级结构的数据表
本文关键字:保留 子层 数据表 结构 转换 层次结构 lt gt 读取 将父 列表 | 更新日期: 2023-09-27 17:58:10
我已经用单元名称转换了这个XML树:Dim=尺寸
Dim1
|---MG1
|---M1
|---M2
|---M3
|---MG31
|---MG32
Dim2
|---MG220
|---MG2222
进入一个单位列表,也就是列表,每个单位都可以有另一个层次不受限制的列表。现在,我想将List转换为具有父/子层次结构的表格格式。
数据表应该是这样的:
Dimension...Parent..Child
Dim1........Dim1....MG1
Dim1........MG1.....M1
Dim1........MG1.....M2
Dim1........Dim1....MG2
Dim1........MG1.....M3
Dim1........M3......MG31
Dim1........M3......MG32
Dim2........Dim2....MG220
Dim2........MG220...MG2222
public class Unit
{
public String Name { get; set; }
public Unit Dimension { get; set; }
public UnitParent { get; set; }
public List<Unit> Children { get; set; }
}
问题:如何迭代List并将所有数据写入DataTable?我一定找不到一个棘手的算法。
递归是正确的方法,但我将建议使用LINQ方法,尤其是当这个问题被标记为LINQ时。
LINQ的一个好处是,扩展方法可以消除很多复杂性,留下简单的查询来简单地表达业务逻辑。
下面是我用来压平递归结构的方法:
public static IEnumerable<T> Flatten<T>(this Func<T, IEnumerable<T>> @this, T root)
{
var head = new [] { root, };
var tail =
from c in @this(root)
where !c.Equals(root)
from d in @this.Flatten(c)
select d;
return head.Concat(tail);
}
请注意对Flatten
的递归调用,这是在函数上定义的扩展方法,该函数从给定的父项返回子项。
现在我们可以这样定义Func<T, IEnumerable<T>>
:
Func<Unit, IEnumerable<Unit>> f = u => u.Children;
然后,假设所有Dimension
、Parent
和Children
属性都不为空,我们可以使用此查询生成要添加到表中的记录列表:
var records =
from r in dimensions
from d in f.Flatten(r)
select new
{
Dimension = d.Dimension.Name,
Parent = d.Parent.Name,
d.Name,
};
现在,如果其中任何一个属性是null
,则修复方法如下。
将f
重新定义为:
Func<Unit, IEnumerable<Unit>> f = u => u.Children ?? new List<Unit>();
并添加此扩展方法:
public static R ValueOrNull<T, R>(this T @this, Func<T, R> selector)
where R : class
{
return @this != null ? selector(@this) : null;
}
现在查询的工作方式如下:
var records =
from r in dimensions
from d in f.Flatten(r)
select new
{
Dimension = d.Dimension.ValueOrNull(x => x.Name),
Parent = d.Parent.ValueOrNull(x => x.Name),
d.Name,
};
仍然非常相似,但null
是安全的。
我希望这能有所帮助。
一个简单的递归算法会很好。。。
function AddSubTree(Unit unit) {
if (unit != unit.Dimension)
AddItemToDataTable(unit.Dimension.Name, unit.UnitParent.Name, unit.Name);
foreach (Unit childUnit in unit.Children) {
AddSubTree(childUnit);
}
}
您为每个具有的维度对象调用AddSubTree