比较两个对象列表,并根据某些属性选择常用和差异记录

时间:2012-03-29 13:14:17

标签: c# linq

如何根据属性list Alist B对象类型人与Name人进行比较,并获取另一个list C包含两个列表中常见的人{} {1}}但不在list D中的{1}}

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

我的答案与其他人的答案相似,但前半部分使用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();
    }
}

答案 2 :(得分:0)

简短的回答如下:

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中的对象;使用Object.ReferenceEquals()进行比较,如果您将(a, b) => a更改为(a, b) => b,则该方法将失败。 要避免这种情况,您必须实现IEqualityComparer<Person>并将其传递给方法Except(),如下所示:

var comparer = new PersonComparer(); // the class that implements IEqualityComparer<Person>
var d = listA.Except(c, comparer).ToList();