Reputation: 1362
In this sample how to get only Foos that have any active Bar and return only the active Bars in the collection?
One possible solution is something like this, but it requires recreate the Foo elements:
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; }
}
Edit 1
The objective is to get only Foos with any active Bar and for these Foos, just the Bars that was active.
FooA
Bar1 (Active)
Bar2 (Inactive)
FooB
Bar3 (Inactive)
Bar4 (Inactive)
FooC
Bar5 (Active)
Bar6 (Active)
Disired result:
FooA
Bar1 (Active)
FooC
Bar5 (Active)
Bar6 (Active)
As pointed theres many simple solutions, but I'm wondering if the Linq has any way to do this without retrieve all Bars and then drop the inactive in a loop-like after all Bars was retrieve in memory.
Upvotes: 1
Views: 5926
Reputation: 4906
You need to use
Adding the Data to List
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);
Fetching the Active Data Only
List<Foo> newList = employees.Select(m => new Foo
{
Name = m.Name,
Bars = m.Bars.Where(u => u.IsActive == true).ToList()
}).ToList();
return newList;
Upvotes: 1
Reputation: 1332
You can process the Foo objects in the select clause. Lambdas don't have to be simple expressions, they can contain multiple statements.
var cleanedList = fooList.Where(f => f.Bars.Any(b => b.IsActive))
.Select(f => {
f.Bars.RemoveAll(b => !b.IsActive);
return f;
}
);
Upvotes: 0
Reputation: 25623
If you want a list of the active Bar
instances pulled from all Foo
, but don't need to know which Foo
instances they came from, this should work for you:
var activeBars = fooList.SelectMany(f => f.Bars)
.Where(b => b.IsActive)
// .Distinct() /* eliminate duplicates if you want */
.ToList();
The SelectMany
operator concatenates the Bars
from every Foo
into a single sequence. The Where
operator filters out just the active ones. ToList()
forces a snapshot to be populated immediately.
This gives you a List<Bar>
containing only the Bar
instances where IsActive == true
. If two or more Foo
might contain the same Bar
, and you want to eliminate those duplicates, then add a Distinct()
operator before ToList()
.
Upvotes: 0
Reputation: 101681
If you don't want to re-create Foo's
then use a loop
foreach(var foo in fooList.Where(f => f.Bars.Any(b => b.IsActive)))
{
foo.Bars = foo.Bars.Where(b => b.IsActive).ToList();
}
Upvotes: 0