选择匹配条件的第一个对象或内部对象

时间:2015-06-16 11:11:23

标签: c# lambda ienumerable

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

class Foo 
{
   string SearchId;
   List<Foo> GroupedPackages
}

我想返回符合条件的第一个“foo”实例,它可以在主实例中或在内部列表中。

这就是我到目前为止 - 它有点难看,但它有效:

Package = response.lst.Where(p => p.SearchId == SearchId || 
                                 (p.GroupedPackages != null &&
                                  p.GroupedPackages.Any(m => m.SearchId==SearchId)))
                                                   .FirstOrDefault();
if (Package != null)
{
    if (Package.SearchId != SearchId) 
    {

        Package = Package.GroupedPackages.FirstOrDefault(m => m.SearchId == SearchId);
    }
 }

其中“response.lst”是foo的列表,而Package是foo。

如果可能的话,我希望在单行lambda表达式

中进行

3 个答案:

答案 0 :(得分:2)

这会在顶层或Foo中的任意SearchId个实例中选择指定Foo的第一个GroupedPackages

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

答案 1 :(得分:1)

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

以下是如何扁平化列表:

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 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);

得到的可枚举是:

result

那么这样做很简单:

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

答案 2 :(得分:0)

我首先向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);