Select 第一个符合条件的对象或内部对象
Select the first object that match condition or an inner object
我有一个 class,其中包含相同 class 的内部列表,
例如:
class Foo
{
string SearchId;
List<Foo> GroupedPackages
}
我要return第一个"foo"符合条件的实例,可以在主实例中,也可以在内部List中。
这是我目前所拥有的——它有点难看,但它有效:
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 表达式中完成
这会在顶层或 GroupedPackages
中的任何 Foo
实例中选择具有指定 SearchId
的第一个 Foo
。
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;
}
}
然后添加一个函数来查找自己或者children
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 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();
我有一个 class,其中包含相同 class 的内部列表, 例如:
class Foo
{
string SearchId;
List<Foo> GroupedPackages
}
我要return第一个"foo"符合条件的实例,可以在主实例中,也可以在内部List中。
这是我目前所拥有的——它有点难看,但它有效:
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 表达式中完成
这会在顶层或 GroupedPackages
中的任何 Foo
实例中选择具有指定 SearchId
的第一个 Foo
。
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;
}
}
然后添加一个函数来查找自己或者children
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 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();