-1

I have following list.

One list with Person object has Id & Name property. Other list with People object has Id, Name & Address property.

List<Person> p1 = new List<Person>();
p1.Add(new Person() { Id = 1, Name = "a" });
p1.Add(new Person() { Id = 2, Name = "b" });
p1.Add(new Person() { Id = 3, Name = "c" });
p1.Add(new Person() { Id = 4, Name = "d" });

List<People> p2 = new List<People>();
p2.Add(new People() { Id = 1, Name = "a", Address=100 });
p2.Add(new People() { Id = 3, Name = "x", Address=101 });
p2.Add(new People() { Id = 4, Name = "y", Address=102 });
p2.Add(new People() { Id = 8, Name = "z", Address=103 });

Want to filter list so I used below code. But code returns List of Ids. I want List of People object with matched Ids.

var filteredList = p2.Select(y => y.Id).Intersect(p1.Select(z => z.Id));
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
user2323308
  • 759
  • 5
  • 16
  • 34
  • 1
    `Join` p1 and p2 on Id – ASh Aug 19 '16 at 11:10
  • What exactly are you trying to do? Do you just want a list of people where the same Id exists in the Person collection? – DavidG Aug 19 '16 at 11:11
  • 1
    How is it possible that the same 'Id' of a 'Person' has different name? And what is exactly that you want to achieve? – llouk Aug 19 '16 at 11:15
  • Kindly ignore values in the list. These are dummy values. Need list of people where same Id exists in the person class – user2323308 Aug 19 '16 at 11:18

3 Answers3

7

You're better off with Join

var filteredList = p2.Join(p1, 
        people => people.Id, 
        person => person.Id, 
        (people, _) => people)
    .ToList();

The method will match items from both lists by the key you provide - Id of the People class and Id of Person class. For each pair where people.Id == person.Id it applies the selector function (people, _) => people. The function says for each pair of matched people and person just give me the people instance; I don't care about person.

RePierre
  • 9,358
  • 2
  • 20
  • 37
  • Can you please explain how it works. I don't understand - p=>p.Id, p=>p.Id, (people, _)=>people – user2323308 Aug 19 '16 at 11:20
  • @user2323308 - Please check is [SO Documentation](http://stackoverflow.com/documentation/c%23/68/linq-queries/2994/joins-inner-left-right-cross-and-full-outer-joins#t=201608191121456680136) – Gilad Green Aug 19 '16 at 11:22
  • In simple words: find intersection `p2` with `p1` by `Id` field in p2 and `ID` in `p1` and from pair of `p2_item` and p`1_item` select `p2_item` – Artiom Aug 19 '16 at 11:27
  • @GiladGreen - I know different types of joins. But syntax in the answer unable to understand. What is significance of (People, _) in the above answer – user2323308 Aug 19 '16 at 11:28
  • the `_` is just the name of the parameter that he chose – Gilad Green Aug 19 '16 at 11:28
  • @user2323308 _ is a name of variable, same as p, a, v,..... In this case _ is an object of Person type – Artiom Aug 19 '16 at 11:29
0

Something like this should do the trick :

var result= p1.Join(p2, person => person.Id, people => people.Id, (person, people) => people);
Quentin Roger
  • 6,410
  • 2
  • 23
  • 36
0

If your list is large enough you should use hashed collection to filter it and improve performance:

var hashedIds = new HashSet<int>(p1.Select(p => p.Id));
var filteredList = p2.Where(p => hashedIds.Contains(p.Id)).ToList();

This will work and work extremely fast because Hashed collections like Dictionary or HashSet allows to perform fast lookups with almost O(1) complexity (which effectively means that in order to find element with certain hash compiler knows exactly where to look for it. And with List<T> to find certain element compiler would have to loop the entire collection in order to find it.

For example line: p2.Where(p => p1.Contains(p.Id)).ToList(); has complexity of O(N2) because using of both .Where and .Contains will form nested loops.

Do not use the simplest answer (and method), use the one that better suits your needs.

Simple performance test against .Join() ...

And the larger collection is the more difference it would make.

Fabjan
  • 13,506
  • 4
  • 25
  • 52
  • You are right that this will work much faster but maybe explain why :) – Gilad Green Aug 19 '16 at 11:26
  • Join complexity: http://stackoverflow.com/a/2799543/1506454; as for performance test, if number of unique Ids not 100 in 20k, but 20k in 20k, `Join` is pretty fast – ASh Aug 19 '16 at 12:23
  • @ASh Yes, `Join()` method is optimized and it's complexity is good but not better than Where+Contains using HashTable. The problem with Join is that it does some additional checks and other operations that reduce the overall performance. – Fabjan Aug 19 '16 at 12:36