C# 选择符合条件的第一个对象或内部对象

C# 选择符合条件的第一个对象或内部对象,c#,lambda,ienumerable,C#,Lambda,Ienumerable,我有一个类,它包含同一类的内部列表, 例如: class Foo { string SearchId; List<Foo> GroupedPackages } 其中“response.lst”是一个foo列表,包是foo 如果可能的话,我希望在一行lambda表达式中执行此操作这将选择第一个Foo,并在顶层或GroupedPackages中的任何Foo实例中使用指定的SearchId Package = response.lst .Concat(respons

我有一个类,它包含同一类的内部列表, 例如:

class Foo 
{
   string SearchId;
   List<Foo> GroupedPackages
}
其中“response.lst”是一个foo列表,包是foo


如果可能的话,我希望在一行lambda表达式中执行此操作

这将选择第一个
Foo
,并在顶层或
GroupedPackages
中的任何
Foo
实例中使用指定的
SearchId

Package = response.lst
    .Concat(response.lst
        .Where(x => x.GroupedPackages != null)
        .SelectMany(x => x.GroupedPackages)
    )
    .FirstOrDefault(x => x.SearchId == SearchId); 

我首先向Foo添加一个检查条件的函数:

class Foo {
  public bool FulfillsCondition(int searchId) {
     return this.SearchId==searchId;
  }
}
然后添加一个函数来查找自身或子对象

class Foo {
  public Foo FindItemToFulfillCondition(int searchId) {
     if (this.FulfillsCondition) return this;
     return GroupedPackages.FirstOrDefault(p => p.FulfillsCondition);
  }
}
那你就可以

response.lst.Where(p => p.FindItemToFulfillCondition != null);

在搜索之前,您需要先将列表展平

下面是如何将列表展平:

Func<IEnumerable<Foo>, IEnumerable<Foo>> flatten = null;
flatten = fs =>
    from f0 in fs
    from f1 in new [] { f0, }.Concat(flatten(f0.GroupedPackages))
    select f1;
结果可枚举项如下所示:

因此,这样做变得很简单:

var result = flatten(foos).Where(f => f.SearchId == SearchId).FirstOrDefault();

第一个是深度优先还是广度优先?您可能正在查找
SelectMany()
您当前只搜索结构中的一个级别。你打算递归地寻找第一个吗?所以如果你需要一个不同的条件,你必须写另一个函数?这基本上和我做的一样,只是有一个额外的方法。这是一个更好的一点,但我正在寻找像蒂姆的东西answer@Tim:当然,您也可以编写一个函数并给出一个ExpressionT>而不是一个固定的参数,但我想表达的想法是将条件放在一个地方,而不是为父元素和子元素分别编写条件。感谢您的想法,这似乎有点太复杂了不,只有一个层次的深度啊,那么,是的,它比你需要的更复杂。我建议您使用错误的结构,因为您的
Foo
类确实允许多个级别。您将如何构建它以允许一个级别?@zivweisman-如下所示:
class Foo{string SearchId;}class foooroot:Foo{List GroupedPackages;}
-然后顶级列表的类型是
foooroot
var foos = new List<Foo>()
{
    new Foo()
    {
        SearchId = "Y",
        GroupedPackages = new List<Foo>()
        {
            new Foo() { SearchId = "X" },
            new Foo() { SearchId = "Z" },
            new Foo()
            {
                SearchId = "W",
                GroupedPackages = new List<Foo>()
                {
                    new Foo() { SearchId = "G" },
                    new Foo() { SearchId = "H" },
                }
            }
        }
    }
};
flatten(foos);
var result = flatten(foos).Where(f => f.SearchId == SearchId).FirstOrDefault();