使用Linq选择集合子集
本文关键字:子集 集合 选择 Linq 使用 | 更新日期: 2023-09-27 18:19:19
在本示例中,如何仅获取具有任何活动栏的foo,并仅返回集合中的活动栏?
一个可能的解决方案是这样的,但它需要重新创建Foo元素:
fooList
.Where(f => f.Bars.Any(b => b.IsActive))
.Select(f => new Foo()
{
Name = f.Name,
Bars = f.Bars.Where(b => b.IsActive).ToList()
});
public class Foo
{
public string Name { get; set; }
public ICollection<Bar> Bars { get; set; }
}
public class Bar
{
public string Name { get; set; }
public bool IsActive { get; set; }
}
编辑1
目标是只获取具有活动Bar 和的foo,仅获取活动Bar。
FooA
Bar1 (Active)
Bar2 (Inactive)
FooB
Bar3 (Inactive)
Bar4 (Inactive)
FooC
Bar5 (Active)
Bar6 (Active)
的向往的结果:
FooA
Bar1 (Active)
FooC
Bar5 (Active)
Bar6 (Active)
正如所指出的有许多简单的解决方案,但我想知道Linq是否有任何方法可以做到这一点,而无需检索所有bar,然后在循环中放弃非活动,就像所有bar在内存中检索一样。
你需要使用
向列表中添加数据
List<Foo> employees = new List<Foo>();
Foo employee = new Foo();
employee.Name = "Emp1";
employee.Bars = new List<Bar>();
employee.Bars.Add(new Bar { Name = "Alpesh", IsActive = true });
employee.Bars.Add(new Bar { Name = "Krunal", IsActive = true });
employee.Bars.Add(new Bar { Name = "Karthik", IsActive = false });
employee.Bars.Add(new Bar { Name = "Rakesh", IsActive = true });
employees.Add(employee);
只获取活动数据
List<Foo> newList = employees.Select(m => new Foo
{
Name = m.Name,
Bars = m.Bars.Where(u => u.IsActive == true).ToList()
}).ToList();
return newList;
如果您不想重新创建Foo's
,则使用循环
foreach(var foo in fooList.Where(f => f.Bars.Any(b => b.IsActive)))
{
foo.Bars = foo.Bars.Where(b => b.IsActive).ToList();
}
如果您想要从所有Foo
中提取活动Bar
实例的列表,但不需要知道它们来自哪个Foo
实例,这应该为您工作:
var activeBars = fooList.SelectMany(f => f.Bars)
.Where(b => b.IsActive)
// .Distinct() /* eliminate duplicates if you want */
.ToList();
SelectMany
运算符将每个Foo
中的Bars
连接成一个序列。Where
操作符只过滤掉活动的操作符。ToList()
强制立即填充快照
这给您一个List<Bar>
,它只包含Bar
实例,其中IsActive == true
。如果两个或多个Foo
可能包含相同的Bar
,并且您希望消除这些重复,则在ToList()
之前添加Distinct()
操作符。
可以在select子句中处理Foo对象。lambda不一定是简单的表达式,它们可以包含多个语句。
var cleanedList = fooList.Where(f => f.Bars.Any(b => b.IsActive))
.Select(f => {
f.Bars.RemoveAll(b => !b.IsActive);
return f;
}
);