使用Linq选择集合的子集

时间:2014-08-25 19:20:00

标签: c# linq

在此示例中,如何仅获取具有任何活动Bar的Foos并仅返回集合中的活动Bars?

一种可能的解决方案是这样的,但它需要重新创建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

目标是只为这些Foos获得带有任何有效Bar 的Foos,只有活动的条。

FooA
    Bar1 (Active)
    Bar2 (Inactive)
FooB
    Bar3 (Inactive)
    Bar4 (Inactive)
FooC
    Bar5 (Active)
    Bar6 (Active)

令人失望的结果:

FooA
    Bar1 (Active)
FooC
    Bar5 (Active)
    Bar6 (Active)

正如所提到的许多简单的解决方案,但我想知道Linq是否有任何方法可以在不检索所有Bars的情况下执行此操作,然后在内存中检索所有Bars之后将其置于循环状态。

4 个答案:

答案 0 :(得分:1)

您需要使用

将数据添加到列表

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;

答案 1 :(得分:0)

如果您不想重新创建Foo's,请使用循环

foreach(var foo in fooList.Where(f => f.Bars.Any(b => b.IsActive)))
{
    foo.Bars = foo.Bars.Where(b => b.IsActive).ToList();
}

答案 2 :(得分:0)

如果您想要从所有Bar中提取活动Foo个实例的列表,但不需要知道它们来自哪个Foo个实例,这应该对您有用:

var activeBars = fooList.SelectMany(f => f.Bars)
                        .Where(b => b.IsActive)
                     // .Distinct() /* eliminate duplicates if you want */
                        .ToList();

SelectMany运算符将每个Bars的{​​{1}}连接成一个序列。 Foo运算符仅过滤掉活动的运算符。 Where强制立即填充快照。

这会为您提供ToList()仅包含List<Bar>Bar个实例。如果两个或多个IsActive == true可能包含相同的Foo,并且您希望消除这些重复项,请在Bar之前添加Distinct()运算符。

答案 3 :(得分:0)

您可以在select子句中处理Foo对象。 Lambdas不必是简单的表达式,它们可以包含多个语句。

var cleanedList = fooList.Where(f => f.Bars.Any(b => b.IsActive))
                         .Select(f => {
                                          f.Bars.RemoveAll(b => !b.IsActive); 
                                          return f;
                                      }
                                 );