Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 阅读通用列表<;T>;将父/子层次结构放入保留父/子层次结构的数据表中_C#_Linq_Recursion_Tree_Parent Child - Fatal编程技术网

C# 阅读通用列表<;T>;将父/子层次结构放入保留父/子层次结构的数据表中

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 …进入一个单元列表,也称为列表,其中每个单元都可以有另一个具有无限层次结构的列表。现在,我想将列表转换为具有父/子层次结构的表格格式 这样,

我已将此XML树转换为单位名称: 尺寸=尺寸

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,
    };