我有两个列表,其中填充了自己的数据。 假设有两个型号
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?
提前致谢!
与其创建新对象,不如检查属性作为 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();
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);
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);
我创建了这个扩展方法: 请注意,第二个序列可以具有不同的类型,但是您必须指定每个序列中的键以及可选的比较器。
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