Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exclude items of one list in another with different object data types, LINQ?

I have two lists filled with their own data. lets say there are two models Human and AnotherHuman. Each model contains different fields, however they have some common fields like LastName, FirstName, Birthday, PersonalID.

List<Human> humans = _unitOfWork.GetHumans();
List<AnotherHuman> anotherHumans = _unitofWork.GetAnotherHumans();

I would like to exclude the items from list anotherHumans where LastName, FirstName, Birthday are all equal to the corresponding fields of any item in list humans.

However if any item in anotherHumans list has PersonalID and item in list humans have the same PersonalID, then it is enough to compare Human with AnotherHuman only by this PersonalID, otherwise by LastName, FirstName and Birthday.

I tried to create new list of dublicates and exclude it from anotherHumans:

List<AnotherHuman> duplicates = new List<AnotherHuman>();
foreach(Human human in humans)
{
   AnotherHuman newAnotherHuman = new AnotherHuman();
   newAnotherHuman.LastName = human.LastName;
   newAnotherHuman.Name= human.Name;
   newAnotherHuman.Birthday= human.Birthday;
   duplicates.Add(human) 
}
anotherHumans = anotherHumans.Except(duplicates).ToList();

But how can I compare PersonalID from both lists if it presents (it is nullable). Is there any way to get rid from creating new instance of AnotherHuman and list of duplicates and use LINQ only?

Thanks in advance!

like image 677
Gyuzal R Avatar asked Oct 23 '13 10:10

Gyuzal R


3 Answers

Instead of creating new objects, how about checking the properties as part of the linq query

List<Human> humans = _unitOfWork.GetHumans();
List<AnotherHuman> anotherHumans = _unitofWork.GetAnotherHumans();

// Get all anotherHumans where the record does not exist in humans
var result = anotherHumans
               .Where(ah => !humans.Any(h => h.LastName == ah.LastName
                               && h.Name == ah.Name
                               && h.Birthday == ah.Birthday
                               && (!h.PersonalId.HasValue || h.PersonalId == ah.PersonalId)))
               .ToList();
like image 181
NinjaNye Avatar answered Nov 15 '22 15:11

NinjaNye


var duplicates = from h in humans
                 from a in anotherHumans
                 where (h.PersonalID == a.PersonalID) ||
                       (h.LastName == a.LastName && 
                        h.FirstName == a.FirstName && 
                        h.Birthday == a.Birthday)
                 select a;

anotherHumans = anotherHumans.Except(duplicates);
like image 24
Sergey Berezovskiy Avatar answered Nov 15 '22 14:11

Sergey Berezovskiy


var nonIdItems = anotherHumans
   .Where(ah => !ah.PersonalID.HasValue)
   .Join(humans, 
         ah => new{ah.LastName, 
           ah.FirstName, 
           ah.Birthday}, 
         h => new{h.LastName, 
           h.FirstName, 
           h.Birthday}, 
         (ah,h) => ah);
var idItems = anotherHumans
   .Where(ah => ah.PersonalID.HasValue)
   .Join(humans, 
         ah => ah.PersonalID
         h => h.PersonalID, 
         (ah,h) => ah);
var allAnotherHumansWithMatchingHumans = nonIdItems.Concat(idItems);
var allAnotherHumansWithoutMatchingHumans = 
      anotherHumans.Except(allAnotherHumansWithMatchingHumans);
like image 2
spender Avatar answered Nov 15 '22 15:11

spender