将列表与Linq进行比较,选择ID出现在一个列表中的记录

时间:2013-06-27 14:21:24

标签: c# linq

我是Linq的新手,我尝试根据字段过滤两个列表中的记录。 每个列表都有一个ID,我想记录ID出现在一个列表中但不出现在另一个列表中的任何记录。 我只用一个ID列表就可以做到这一点:

List1 = _class1.getList1();
List2 = _class2.getList2();

(为了介绍目的,我使用的是一个我想摆脱的类,它有一个数据列表,还有一个ID的列表,我应该能够只用数据列表来做将list1与list2进行比较的两个语句,反之亦然)

var inList1ButNot2 = List1.IDList.Except(List2.IDList);
var inList2ButNot1 = List2.IDList.Except(List1.IDList);

我遇到麻烦的地方是使用数据列表来比较第二个列表的ID字段。我相信它应该是这样的:

var inList1ButNot2 = DataList1.Select(x => x.ID)
        .Except(DataList2.Select(y => y.ID));

问题在于我没有把整个记录只是我正在比较的字段,我是否需要在之后单独选择每个字段,或者在语句中是否有一种方法可以选择记录如果ID出现在一个字段中列表但不是另一个?

6 个答案:

答案 0 :(得分:3)

所以你真正想要的是ExceptBy方法;你希望能够在每个元素的投影上执行Except,而不是在元素iteself上执行public static IEnumerable<TSource> ExceptBy<TSource, TKey>( this IEnumerable<TSource> source, IEnumerable<TSource> other, Func<TSource, TKey> selector, IEqualityComparer<TKey> comparer = null) { comparer = comparer ?? EqualityComparer<TKey>.Default; var set = new HashSet<TKey>(other.Select(selector), comparer); foreach (var item in source) if (set.Add(selector(item))) yield return item; } 。以下是这种方法的实现:

var inList1ButNot2 = DataList1.ExceptBy(DataList2, item => item.ID);
var inList2ButNot1 = DataList2.ExceptBy(DataList1, item => item.ID);

现在你可以做到:

{{1}}

答案 1 :(得分:2)

可能有更好的方法,但是:

var inList1ButNot2 = DataList1.Where(x => !(DataList2.Any(y => y.ID == x.ID)));

注意:我是自由的,所以可能会有拼写错误。

答案 2 :(得分:0)

        var list1 = new List<Asd>();
        var list2 = new List<Asd>();

        var asd = new Asd() {Id = 1, Name = "asd"};
        var asd2 = new Asd() {Id = 2, Name = "asd"};
        var asd3 = new Asd() {Id = 3, Name = "asd"};
        var asd4 = new Asd() {Id = 4, Name = "asd"};
        var asd5 = new Asd() {Id = 5, Name = "asd"};

        list1.Add(asd);
        list1.Add(asd2);
        list1.Add(asd3);

        list2.Add(asd);
        list2.Add(asd4);
        list2.Add(asd5);

        var onlyInFirstList = list1.Where(x => !list2.Any(y => y == x));
        var onlyInSecondList = list2.Where(x => !list1.Any(y => y == x));

这应该有效,但不完美但有效:)

答案 3 :(得分:0)

您可以尝试这样的事情。

public void Test(List<List1> list1, List<List2> list2)
{
    var result = from l1 in list1
                 where list2.All(l2 => l1.Id != l2.Id)
                 select l1;

}

或者,如果你有两个属性(我假设它们是不同的类型?)你可以返回一个匿名类型,并从调用者实例返回属性

public void Test(List<List1> list1, List<List2> list2)
{
    var result = from l1 in list1
                 where list2.All(l2 => l1.Id != l2.Id)
                 select new
                 {
                     l1.Id,
                     l1.OtherField1,
                     Test = 10.5, //Example declare new field
                     SomethingElse = this.PropertyXyz; //Set new field = instance property
                 };

}

答案 4 :(得分:0)

不是重写Except中的逻辑(以及所有其他设置操作),而是允许可以为其他类和选择器重用的东西,考虑以下内容:

private class LambdaComparer<T, U> : IEqualityComparer<T>
{
    private Func<T, U> selector;

    public LambdaComparer(Func<T, U> selector)
    {
        this.selector = selector;
    }

    public bool Equals(T x, T y)
    {
        if (x == null && y == null) return true;
        if (x == null || y == null) return false;
        return EqualityComparer<U>.Default.Equals(selector(x), selector(y));
    }

    public int GetHashCode(T obj)
    {
        if (obj == null) return 0;
        return EqualityComparer<U>.Default.GetHashCode(selector(obj));
    }
}

var inList1ButNot2 = List1.IDList.Except(
    List2.IDList,
    new LambdaComparer<ClassWithID, int>(w => w.ID));

答案 5 :(得分:-1)

你可以尝试这样的事情

list1 = list1.Union(list2).Distinct().ToList();