b3n
b3n

Reputation: 3865

How can I filter nested lists with Linq?

I use LINQ on a Dictionary<string, IList<ID>> like this:

var searchCategories = new List {"A", "B", "C"};
Result = CategoryMapper.Mapping.Where(
         x => searchCategories.Contains(x.Key)).
         Select(x => new Tuple<string, IList<ID>>(x.Key, x.Value)).ToList();

This returns all ids that are either in Category A, B or C. However what I would like to do is retrieve ids that are in Category A, B and C.

I'm having difficulties figuring out how to do this with Linq.

UPDATE

I'm sorry but I should have added some more information in my initial post. The lists in my dictionary look somewhat like this (I only use numbers here to make it simple):

A : {1, 2, 3}
B : {1,3}
C : {3}

So what I would like as a result of my query would be '3' in this case because it is the only number that has all categories.

Upvotes: 1

Views: 1692

Answers (3)

Jeff Mercado
Jeff Mercado

Reputation: 134811

Looks like you're just taking the intersection of all the lists. That should be simple to obtain.

var searchCategories = new HashSet<string> { "A", "B", "C" };
var result = CategoryMapper.Mapping
    .Where(map => searchCategories.Contains(map.Key))
    .Select(map => map.Value as IEnumerable<ID>)
    .Aggregate((acc, cur) => acc.Intersect(cur));

If your ID type doesn't implement the IEquatable<ID> interface, then you may need to provide an equality comparer (that I assume you have) to perform the comparisons.

 ....Aggregate((acc, cur) => acc.Intersect(cur, new YourIdEqualityComparer()));

Upvotes: 1

Scott Rippey
Scott Rippey

Reputation: 15810

To get all the ids, the SelectMany method is perfect for this:

var ids = CategoryMapper.Mapping.SelectMany(kv => kv.Value);

Upvotes: 0

grapeot
grapeot

Reputation: 1634

You can try to change x => searchCategories.Contains(x.Key) to x => searchCategories.All(c => x.Key.Contains(c)), i.e. the final code snippet should be

var searchCategories = new List<string> {"A", "B", "C"};
Result = CategoryMapper.Mapping.Where(
     x => searchCategories.All(c => x.Key.Contains(c))).
     Select(x => new Tuple<string, IList<ID>>(x.Key, x.Value)).ToList();

Upvotes: 0

Related Questions