简体   繁体   中英

Comparing two list of different objects

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));

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 .

这样的事情应该可以解决问题:

var result= p1.Join(p2, person => person.Id, people => people.Id, (person, people) => people);

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM