Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# linq expression in lambda with contains

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.

like image 852
codingjoe Avatar asked Feb 20 '14 21:02

codingjoe


2 Answers

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();
like image 142
Selman Genç Avatar answered Oct 08 '22 11:10

Selman Genç


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.

like image 42
Markus Avatar answered Oct 08 '22 10:10

Markus