C# 阅读通用列表<;T>;将父/子层次结构放入保留父/子层次结构的数据表中
我已将此XML树转换为单位名称: 尺寸=尺寸C# 阅读通用列表<;T>;将父/子层次结构放入保留父/子层次结构的数据表中,c#,linq,recursion,tree,parent-child,C#,Linq,Recursion,Tree,Parent Child,我已将此XML树转换为单位名称: 尺寸=尺寸 Dim1 |---MG1 |---M1 |---M2 |---M3 |---MG31 |---MG32 Dim2 |---MG220 |---MG2222 …进入一个单元列表,也称为列表,其中每个单元都可以有另一个具有无限层次结构的列表。现在,我想将列表转换为具有父/子层次结构的表格格式 这样,
Dim1
|---MG1
|---M1
|---M2
|---M3
|---MG31
|---MG32
Dim2
|---MG220
|---MG2222
…进入一个单元列表,也称为列表,其中每个单元都可以有另一个具有无限层次结构的列表。现在,我想将列表转换为具有父/子层次结构的表格格式
这样,datatable应该如下所示:
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; }
}
维度…父..子
Dim1……Dim1……MG1
Dim1……MG1……M1
Dim1……MG1……平方米
Dim1……Dim1……MG2
Dim1……MG1……立方米
Dim1……立方米……MG31
Dim1……M3……MG32
Dim2……Dim2……MG220
Dim2……MG220……MG2222
公营课组
{
公共字符串名称{get;set;}
公共单位维度{get;set;}
公共UnitParent{get;set;}
公共列表子项{get;set;}
}
问题:如何迭代列表并将所有数据写入DataTable?
一定有一个棘手的算法我找不到。一个简单的递归算法就可以了
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
,递归是正确的方法,但我将建议使用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);
}
然后,假设所有维度
、父级
和子级
属性都不为空,我们可以使用此查询生成要添加到表中的记录列表:
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>();
仍然非常相似,但null
safe
我希望这有帮助。不起作用。传递给AddSubTree的单元通常为null,引发异常。实际上维度不应该为空。。。我想如果不把所有的源代码都放在这里,这个问题是无法解决的。。。对不起,谢谢你的帮助。我现在要玩了…谢谢。我给了你一个好的片段,我肯定可以用另一天。不是解决方案,因为我意识到现有的代码结构与我认为/预期的不同,因此需要另一个非常简单的解决方案:)
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,
};