【问题标题】:Flattening a tree of classes using SelectMany()使用 SelectMany() 展平类树
【发布时间】:2017-06-21 01:40:52
【问题描述】:

我有一个跟踪所有者类之间关系的类。树可能是无限的——在数据库中,每条记录都有一个父 ID,它是对同一个表的自引用。这个类基本上是这样的:

public class ObjectRelation
{

    public ObjectRelation(GetObjectParentChildList_Result relation)
    {
        this.ObjectId = relation.Object_ID;
        this.ParentObjectId = relation.Parent_Object_ID;
        this.ChildObjects = new List<ObjectRelation>();
    }

    public int ObjectId { get; set; }
    public int? ParentObjectId { get; set; }
    public List<ObjectRelation> ChildObjects { get; set; }

}

我希望有一种方法可以引用此类的单个实例,最终在一个列表中列出树中每个唯一 ID 的列表,以确保用户在输入数据时不会创建无限的父/子循环(即,ID 1 和 2 是彼此的父母),看起来 SelectMany 是要走的路。这样的查询在 LINQ 中是否可行,或者我是否坚持编写单独的方法来递归整个树并在我用完子节点时返回计算的 ID 列表?

【问题讨论】:

  • 这是树还是有向图?树不能有无限的专利子循环。
  • Here is a solution that requires a tree。它不适用于带有循环的图,也不会删除重复项。
  • ObjectRelation 应该有一个父属性,然后只需在图表上导航以查找重复的 id。或者在 ObjectRelation 上创建一个名为 Parent 的扩展方法,该方法返回一个 IEnumerable,然后检查是否有任何 Parent 是有问题的孩子。 if (x.Parents.Any(p=&gt;p.ObjectId == x.ObjectId)) throw Exception();

标签: c# linq tree


【解决方案1】:
public class ObjectRelation
{
    public ObjectRelation(GetObjectParentChildList_Result relation)
    {
        this.ObjectId = relation.Object_ID;
        this.Parent = relation.Parent_Object;
        this.ChildObjects = new List<ObjectRelation>();
    }

    public int ObjectId { get; set; }
    public ObjectRelation Parent { get; set; }
    public List<ObjectRelation> ChildObjects { get; set; }
}

public static class ObjectRelationExtensions
{
  public static IEnumerable<ObjectRelation> Parents(this ObjectRelation obj)
  {
    while(obj.Parent!=null)
    {
      obj = obj.Parent;
      yield return obj;
    }
  }
}

然后检查:

if (x.Parents.Any(p=>p==x)) throw Exception();

if (x.Parents.Any(p=>p.ObjectId==x.ObjectId)) throw Exception();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 2014-05-24
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    相关资源
    最近更新 更多