比较两个对象列表,并根据某些属性选择常见记录和差异记录
本文关键字:记录 属性 选择 常见 两个 对象 列表 比较 | 更新日期: 2023-09-27 18:29:19
如何基于属性Name
将对象类型person的list A
与person的list B
进行比较,并获得另一个包含两个列表中共同的list C
和位于list A
但不位于list B
的list D
?
var a = new List<int>();
var b = new List<int>();
var c = new List<int>();
var d = new List<int>();
c = a.Where(aItem => b.Any(bItem => aItem == bItem)).ToList();
d = a.Except(c).ToList();
你可以使用任何逻辑来比较一个项目和另一个项目。
以下是实现这一点的扩展方法。
public static class LinqEx
{
public static bool DefaultCompare<T>(T one, T two)
{
return one.Equals(two);
}
public static IEnumerable<T> Common<T>(this IEnumerable<T> first, IEnumerable<T> second)
{
return first.Common(second, DefaultCompare);
}
public static IEnumerable<T> Common<T>(this IEnumerable<T> first, IEnumerable<T> second, Func<T, T, bool> compare)
{
return first.Where(i1 => second.Any(i2 => compare(i1, i2)));
}
public static IEnumerable<T> Common<T>(this IEnumerable<T> first, IEnumerable<T> second, out IEnumerable<T> difference)
{
return first.Common(second, out difference, DefaultCompare);
}
public static IEnumerable<T> Common<T>(this IEnumerable<T> first, IEnumerable<T> second, out IEnumerable<T> difference, Func<T, T, bool> compare)
{
var common = first.Common(second, compare);
difference = first.Except(common);
return common;
}
public static IEnumerable<T> Common<T>(this IEnumerable<T> first, IEnumerable<T> second, out List<T> difference)
{
IEnumerable<T> d;
var common = first.Common(second, out d);
difference = d.ToList();
return common;
}
public static IEnumerable<T> Common<T>(this IEnumerable<T> first, IEnumerable<T> second, out List<T> difference, Func<T, T, bool> compare)
{
IEnumerable<T> d;
var common = first.Common(second, out d, compare);
difference = d.ToList();
return common;
}
}
用法:
List<myObjectType> d;
c = a.Common(b, out d, (i1, i2) => i1.Name == i2.Name).ToList();
我的答案与这里的其他答案相似,但在前半部分使用Intersect()
方法,这是我认为最简单、最正确的方法,可以获得两个集合中存在的项目集:
var a = new[] {new Person("Alice"), new Person("Bob")};
var b = new[] {new Person("Bob"), new Person("Charlie")};
var inBoth = a.Intersect(b, new PersonNameEqualityComparer());
var notInB = a.Except(b, , new PersonNameEqualityComparer());
inBoth
将包含Bob,而notInB
将包含Alice。
这里唯一的问题是Intersect
需要一个相等比较器,它可以获得两个Person对象,并根据它们的Name确定它们是否相等。我希望我们可以在这里指定一个lambda表达式,但在此之前,实现非常简单:
class PersonNameEqualityComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
return x.Name == y.Name;
}
public int GetHashCode(Person obj)
{
return obj.Name.GetHashCode();
}
}
简短的答案如下:
var c = listA.Join(listB, a => a.Name, b => b.Name, (a, b) => a).ToList();
var d = listA.Except(c).ToList();
这将根据每个对象的Name
属性连接两个列表,并返回第一个列表中的公共对象。Except()
方法将返回在listA
bot中而不在c
中的对象;使用CCD_ 16进行比较,如果将CCD_ 17更改为CCD_。为了避免这种情况,您必须实现IEqualityComparer<Person>
并将其传递给方法Except()
,如下所示:
var comparer = new PersonComparer(); // the class that implements IEqualityComparer<Person>
var d = listA.Except(c, comparer).ToList();