排除一个列表中具有不同对象数据类型的另一个列表的项目,LINQ?

问题描述 投票:0回答:4

我有两个列表,其中填充了自己的数据。 假设有两个型号

Human
AnotherHuman
。每个模型包含不同的字段,但是它们有一些共同的字段,例如
LastName, FirstName, Birthday, PersonalID

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

我想从列表

anotherHumans
中排除项目,其中
LastName, FirstName, Birthday
都等于列表
humans
中任何项目的相应字段。

但是,如果

anotherHumans
列表中的任何项目具有
PersonalID
且列表
humans
中的项目具有相同的
PersonalID
,则仅通过此
Human
即可将
AnotherHuman
PersonalID
进行比较,否则通过
LastName, FirstName and Birthday

我尝试创建新的重复列表并将其从

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

但是如果它存在(可以为空),我如何比较两个列表中的

PersonalID
。有没有办法摆脱创建 AnotherHuman 的新实例和重复项列表并仅使用 LINQ?

提前致谢!

c# asp.net-mvc linq list
4个回答
21
投票

与其创建新对象,不如检查属性作为 linq 查询的一部分

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

19
投票
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);

2
投票
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);

0
投票

我创建了这个扩展方法: 请注意,第二个序列可以具有不同的类型,但是您必须指定每个序列中的键以及可选的比较器。

  public static IEnumerable<TOuter> Except<TOuter, TInner, TKey>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner,
        Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, IEqualityComparer<TKey> comparer) {
     IEnumerable<TOuter> iguales = outer.Join(
        inner           : inner,
        outerKeySelector: tOuter => outerKeySelector(tOuter),
        innerKeySelector: tInner => innerKeySelector(tInner),
        resultSelector  : (o, _) => o,
        comparer        : comparer);
     return outer.Except(iguales);
  }

以下是如何使用它

     String name = "John";
     Char[] chars = { 'h', 'n' };
     var result = name.Except(
        inner           : chars,
        outerKeySelector: c => c,
        innerKeySelector: c => c); // result will contain J, o
© www.soinside.com 2019 - 2024. All rights reserved.