如何查找嵌套在多级集合中的对象

时间:2013-07-23 10:31:15

标签: c# ienumerable traversal

假设我有一个List<Family>,每个家庭都有List<Child>

当我在代码中遇到Child对象时,如何确定孩子是否属于任何家庭?

伪码:

If Child not in any family
    // Do something with child

更新

示范模型:

class Family
{
  public List<Child> Children {get;set;}
  // Properties
}

class Child
{
  // Properties
}

示例ViewModel:

class FamilyViewModel
{
  public List<Family> Families {get;set;}

  public bool ChildHasFamily(Child child)
  {
     // Determine if child is in any family or not
  } 
}

2 个答案:

答案 0 :(得分:2)

现在这对我来说并不是那么干净。我认为您的Child应该具有Family属性,以简化操作。如果我理解正确,你的视图模型有一个家庭列表,而家庭列表又包含一个孩子列表。当您收到一份儿童名单时,您想知道它是否属于您的一个家庭:

class FamilyViewModel
{
  public List<Family> Families {get;set;}

  public void ChildHasFamily(Child child)
  {
      var hasFamily = Families.SelectMany(f => f.Children)
                              .Contains(child);
  } 
}

请注意,这将进行对象引用比较。如果Child实施IEquatable<Child>,它将开箱即用。如果没有,您可以使用:

class FamilyViewModel
{
  public List<Family> Families {get;set;}

  public void ChildHasFamily(Child child)
  {
      var hasFamily = Families.SelectMany(f => f.Children)
                              .Any(c => c.Name == child.Name);
  } 
}

替换Where谓词以进行身份​​比较。

答案 1 :(得分:0)

您可以使用以下使用延迟执行的递归Traverse方法。

然后很简单:

IEnumerable<Family> familiesOfChild = families.Traverse(f => f.Children)
    .Where(c => c.Equals(yourChild));
if(!familiesOfChild.Any())
{
    // oh, what a poor child
}

这是扩展方法:

public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse)
{
    foreach (T item in source)
    {
        yield return item;

        IEnumerable<T> seqRecurse = fnRecurse(item);
        if (seqRecurse != null)
        {
            foreach (T itemRecurse in Traverse(seqRecurse, fnRecurse))
            {
                yield return itemRecurse;
            }
        }
    }
}