Reputation: 800
I am trying to make use of the 'contains' to simulate the old SQL 'where id in (1,2,3,4)' way of filtering a query.
However I have some difficulties in using it where my id's are in a deeper level.
Code:
public class Category
{
public long Id { get; set; }
public string Name { get; set; }
}
public class Characteristica
{
public Category Category { get; set; }
public int Id { get; set; }
public string Value { get; set; }
}
public class Person
{
public string Name { get; set; }
public List<Characteristica> Appearance { get; set; }
}
class Program
{
static void Main(string[] args)
{
var persons = new List<Person>
{
new Person { Name = "Person A", Appearance = new List<Characteristica> { new Characteristica { Id = 22 }, new Characteristica { Id = 5 }, new Characteristica { Id = 12 } }},
new Person { Name = "Person B", Appearance = new List<Characteristica> { new Characteristica { Id = 1 }, new Characteristica { Id = 6 }, new Characteristica { Id = 11 } }},
new Person { Name = "Person C", Appearance = new List<Characteristica> { new Characteristica { Id = 2 }, new Characteristica { Id = 8 }, new Characteristica { Id = 13 } }},
new Person { Name = "Person D", Appearance = new List<Characteristica> { new Characteristica { Id = 2 }, new Characteristica { Id = 5 }, new Characteristica { Id = 10 } }},
new Person { Name = "Person E", Appearance = new List<Characteristica> { new Characteristica { Id = 1 }, new Characteristica { Id = 8 }, new Characteristica { Id = 10 } }},
new Person { Name = "Person F", Appearance = new List<Characteristica> { new Characteristica { Id = 1 }, new Characteristica { Id = 6 }, new Characteristica { Id = 23 } }},
};
var listOfSearchedIds = new List<int> { 22, 23 };
var selected = persons.Select(p => p.Appearance.Where(a => listOfSearchedIds.Contains(a.Id))).ToList();
}
}
Now I am trying to get 'Person A' and 'Person F' out from my collection by using the contains feauture. However I cannot see what I am doing wrong here.
Can someone shed some light on what I am doing wrong? I have tried different versions of my lambda and this is the closes I can get, but I am getting all 6 items out from my expression.
Upvotes: 15
Views: 113834
Reputation: 22436
Try the following:
var listOfSearchedIds = new List<int> { 22, 23 };
var selected = persons
.Where(p => listOfSearchedIds
.Intersect(p.Appearance
.Select(a => a.Id)).Any()).ToList();
By using Intersect, you compare two lists and return the items that are contained in both of them. Intersect uses a HashSet internally and therefore is a very performant way two find the intersection of two sets. Any() returns true if there is at least one item in the resulting list.
Upvotes: 3
Reputation: 101681
Your way is correct but you should use Where
instead of Select
var selected = persons.Where(p => p.Appearance
.Where(a => listOfSearchedIds.Contains(a.Id))
.Any()).ToList();
And you need to use Any
to check whether the returning sequence from p.Appearance.Where
contains any element.Or you can use Any
directly and make it shorter:
var selected = persons.Where(p => p.Appearance
.Any(a => listOfSearchedIds.Contains(a.Id))
.ToList();
Upvotes: 34