我有两个清单:
List<objA> list1
List<objB> list2
class objA
{
string Name;
}
class objB
{
string Name;
bool SomeProp;
}
使用C#linq / lambda我想选择其Name属性等于第二个obj(list1.Name == list2.Name)的name属性的所有objA对象,并检查objB的另一个属性(list2.SomeProp) == true)。
答案 0 :(得分:7)
我建议使用join:
from a in list1
join b in list2 on a.Name equals b.Name
where b.SomeProp
select a
Lambda语法:
list1.Join(listb.Where(b => b.SomeProp),
a => a.Name, b => b.Name, (a,b) => a)
注意:因此,您将避免枚举list1中每个项目的list2集合(带Any
的解决方案)
显示两个解决方案之间的区别 - 让我们看看在将linq转换为plain循环后它们的样子。首先是
list1.Where(a => list2.Any(b => b.Name == a.Name && b.SomeProp))
相当于
foreach(var a in list1)
{
foreach(var b in list2)
{
if (a.Name == b.Name && b.SomeProp)
{
yield return a;
break;
}
}
}
如您所见 - 它具有嵌套循环,复杂度为O(N * M)。通过join,我们为内部序列创建了Lookup:
Lookup<string, objB> lookup = list2.Where(b => b.SomeProp).ToLookup(b => b.Name);
foreach(var a in list1)
{
Grouping<string, objB> g = lookup.GetGrouping(a.Name);
if (g == null)
continue;
foreach(var b in g)
yield return a;
}
这里的区别是在查找中搜索 - 这是O(1)操作。总复杂度将为O(M + N)
答案 1 :(得分:4)
这应该这样做:
list1.Where(a => list2.Any(b => b.Name == a.Name && b.SomeProp));