Filtering Sublist
-
You have a list of items (Item type A). For each item in that list, you have a sub-list of items (Item type B). You have another independent list of type B. You wish to filter the first list to only contain the items (and sub-items) in your independent list of type B's. You're using C# and LINQ. How the heck do you do it? -Mike.
-
You have a list of items (Item type A). For each item in that list, you have a sub-list of items (Item type B). You have another independent list of type B. You wish to filter the first list to only contain the items (and sub-items) in your independent list of type B's. You're using C# and LINQ. How the heck do you do it? -Mike.
var aList = new List<A>();
var filterList = new List<B>();var res1 = from a in aList
where a.BList.Any(b => filterList.Contains(b))
select a;
// or
var res2 = from a in aList
where a.BList.All(b => filterList.Contains(b))
select a;
// depending on your filtering criteria.For the classes,
class A
{
public List<B> BList;
}class B
{
}Eslam Afifi
-
var aList = new List<A>();
var filterList = new List<B>();var res1 = from a in aList
where a.BList.Any(b => filterList.Contains(b))
select a;
// or
var res2 = from a in aList
where a.BList.All(b => filterList.Contains(b))
select a;
// depending on your filtering criteria.For the classes,
class A
{
public List<B> BList;
}class B
{
}Eslam Afifi
Thanks for the reply. This is close to what I want, but not exactly. The filtering is taking place on A, but not also B. Perhaps an example would help: Lets say List A was called AlphabetList, and had the letters A through Z, each as an object (an item to the list). Now lets say List B was called NumbersList and each instance contained five numbers. For every AlphabetList there is a NumbersList. The sets might look like this: A (1,2,3,4,5) B (6,7,8,9,10) C (11,12,13,14,15) ... if my independent NumbersList contained (7, 14), I'm looking for a LINQ statement which could filter the AlphabetList to contain only the objects marked B and C, and within those, filter the NumbersList items to only contain the objects with the numbers 7 and 14. Thanks. -Mike.
-
Thanks for the reply. This is close to what I want, but not exactly. The filtering is taking place on A, but not also B. Perhaps an example would help: Lets say List A was called AlphabetList, and had the letters A through Z, each as an object (an item to the list). Now lets say List B was called NumbersList and each instance contained five numbers. For every AlphabetList there is a NumbersList. The sets might look like this: A (1,2,3,4,5) B (6,7,8,9,10) C (11,12,13,14,15) ... if my independent NumbersList contained (7, 14), I'm looking for a LINQ statement which could filter the AlphabetList to contain only the objects marked B and C, and within those, filter the NumbersList items to only contain the objects with the numbers 7 and 14. Thanks. -Mike.
You're welcome :) So you want something like this?
var res1 = from a in aList
let matchedInA = a.BList.Intersect(filterList)
where matchedInA.Count() != 0
select new { a, matchedInA };I didn't test the code.
Eslam Afifi
-
You're welcome :) So you want something like this?
var res1 = from a in aList
let matchedInA = a.BList.Intersect(filterList)
where matchedInA.Count() != 0
select new { a, matchedInA };I didn't test the code.
Eslam Afifi
That works, however, I was hoping for a way that didn't return an anonymous type. I wanted to keep the original object containment. The now filtered list of B's still kept inside the respective A's. Starting to think LINQ might not be able to do that. It's a puzzler. :confused: -Mike.
-
That works, however, I was hoping for a way that didn't return an anonymous type. I wanted to keep the original object containment. The now filtered list of B's still kept inside the respective A's. Starting to think LINQ might not be able to do that. It's a puzzler. :confused: -Mike.
You can iterate over the result returned from the query and modify the original collection. I've just had a crazy idea to do it all in the query and I don't know if it will work or not but here it is anyway.
var res1 = from a in aList
let bListOriginalCount = a.BList.Count
let removedCount = a.BList.RemoveAll(b => !filterList.Contains(b))
where removedCount == bListOriginalCount
select a; // will affect ALL items in aList
// or
var res1 = from a in aList
let removedCount = a.BList.RemoveAll(b => !filterList.Contains(b))
where a.BList.Count != 0
select a; // will affect ALL items in aList
// or
var res1 = from a in aList
let matchedInA = a.BList.Intersect(filterList)
where matchedInA.Count() != 0
let dummyA = ((Func<A>)(() =>
{
a.BList.RemoveAll(b => !matchedInA.Contains(b));
return a;
})).Invoke()
select dummyA; // will affect only matched items in aListAnd you can do it with normal loops. LINQ is puzzler at the begining but with time you will find it easy. It's just some extension methods (static methods over IEnumerable...), lambda expressions (anonymous methods) and relational algebra (kinda) :cool: Please let me know which works and which doesn't.
Eslam Afifi