如何在父级的情况下将子项添加到C#中的对象图中?

时间:2010-07-19 02:07:42

标签: c# linq generics

我在C#中有几个对象大致是这样的:

A: {
      Id: 1,
      Parent: {
                 Id: 2,
                 Parent: {
                            Id: 3,
                            Parent: null
                         }}}

B: {
     Id: 4
     Parent: {
               Id: 2
               Parent:
                       { 
                         Id: 3
                         Parent: null
}}}

我想将两者合并并转换,以便它们被反转:

Combined: {
             Id 3:
             Child: {
                         Id 2,
                         Child: { 
                                     Id: 4,
                                     Child: null
                         Child: {    Id: 1,
                                     Child: null
}}}

这些课程如下:

Public Class MyObject {
    public string Id;
    public MyObject Parent;
}

public Class CombinedObject {
    public string Id;
    public IList<CombinedObject> Child;
}

这应该很容易,应该有一个很好的声明方式来做到这一点,对吧?如果不使用很多丑陋的循环,我无法弄明白。

1 个答案:

答案 0 :(得分:1)

可能有更好的解决方案,但这里有一个问题:

MyObject A = GetA(); 
MyObject B = GetB(); 

List<MyObject> allObjects = 
  GetObjects(A) 
  .Concat(GetObjects(B)) 
  .GroupBy(x => x.Id) //rule out duplicates 
  .Select(g => g.First()) 
  .ToList(); 

ILookup<string, string> lookupByParentId = allObjects 
  .Where(x => x.Parent != null) 
  .ToLookup(x => x.Parent.Id, x => x.Id); 

Dictionary<string, CombinedObject> allCombinedObjects = allObjects 
  .Select(x => new CombinedObject() 
  { 
    Id = x.Id, 
    Children = null;
  }) 
  .ToDictionary(x => x.Id); 

foreach(CombinedObject co in allCombinedObjects.Values)
{
  co.Children = lookupByParentId[co.Id]
    .Select(childId => allCombinedObjects[childId])
    .ToList();
}


HashSet<string> rootNodeKeys = new HashSet(allObjects 
  .Where(x => x.Parent == null) 
  .Select(x => x.Id) 
  ); 

List<CombinedObject> rootNodes = allCombinedObjects.Values
  .Where(x => rootNodeKeys.Contains(x.Id)) 
  .ToList(); 

定义了GetObjects:

public IEnumerable<MyObject> GetObjects(MyObject source)
{
  MyObject current = source;
  while (current != null)
  {
    yield return current;
    current = current.Parent;
  }  
}