使用多个属性上的except过滤列表 [英] Filtering a list using except on multiple properties

查看:73
本文介绍了使用多个属性上的except过滤列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一种方法,该方法最终将给我一个记录集合,而这些记录在我要引用的另一个集合中不再具有相应的记录.

I am trying to write a method which will ultimately give me a collection of records which no longer have a corresponding record within a different collection to which I am referencing.

结构类似于:

public class A
{
    int id {get; set;}
    int recId {get; set;}
    string category {get; set;}
}


public class B
{
    int recId {get; set;}
    string category {get; set;}
}

到目前为止,我使用LINQ的以下内容来收集丢失的记录,但这只会给我丢失的任何recId:

So far I have the following bit of LINQ to give me my collection of missing records but this only giving me any recId that is missing:

var noLongerHaveRecordInCollectionB =
CollectionA.Select(x => x.recId).Except(CollectionB.Select(x => x.recId));

我需要每条记录的List<A>:

1.)CollectionB中不再保存recId.

OR

2.)不再具有CollectionB

对于示例CollectionA中可能有2条记录具有相同的recId但不同的category.

For example it is possible that within CollectionA there are 2 records with the same recId but different category.

如果CollectionB现在仅包含该recId的1条记录,我想删除CollectionA中没有相应类别的记录.

If CollectionB now only contains 1 record for that recId I would want to remove the record in CollectionA which does not have the corresponding category.

所以最终的问题是,如何用已经针对CollectionB检查过的所有<T> A填充noLongerHaveRecordInCollectionB,而不仅仅是像现在这样的recId,我想要整个对象.

So the ultimate question is how can I populate noLongerHaveRecordInCollectionB with all <T> A's that have been checked against CollectionB and not just the recId as it currently does, I want the whole object.

修改:输入/结果

CollectionA

1,2254,类别A

1,2254,Category A

2,2236,类别A

2,2236,Category A

3,2415,类别B

3,2415,Category B

4,1275,类别B< ---与下面相同的人,比较类别

4,1275,Category B <--- same person as below, diff category

5,1275,类别C< ---与上述相同,差异类别

5,1275,Category C <--- same person as above, diff category

CollectionB

2254,类别A

2415,类别B

1275,类别C

预期结果

我希望(来自CollectionA)以下ID在我的列表中突出显示以删除:2,4

I would expect (from CollectionA) the following id's to be highlighted in my list for deletion: 2, 4

推荐答案

使用带有||条件的Where子句,您可以简单地实现所需的内容.无需寻求复杂的解决方案.

You can simply achive what you want by using Where clause with || condition. No need to go for the complex solution.

 var result = collectionA.Where(a => collectionB.Any(b => a.recId == b.recId && a.Category != b.Category)
              || !collectionB.Any(b => b.recId == a.recId));

旧答案

您可以为 IEqualityComparer 实现您的课程并根据您感兴趣的字段比较对象.例如,实现Equals方法,如下所示:

You can implement IEqualityComparer for your class and compare the objects based on the fields you are interested in.For example implement the Equals method like this:

public bool Equals(A a, B b)
{
    return a.recId  == b.recId && a.category == b.category ;
}

然后只需调用Except方法并传递您的comparer:

Then just call Except method and pass your comparer:

var resultList = CollectionA .Except(CollectionB, new MyEqualityComparer());

或者,如果您在类上实现它,而不是单独的comparer,则只需调用Except:

Or if you implement it on your class, instead of a separate comparer you can just call Except:

var resultList = CollectionA .Except(CollectionB);

请注意,您还需要实现GetHashCode方法.

Be aware that you need also implement GetHashCode method.

更新

如果要使用IEqualityComparer<T>,则可以从第二个列表中创建一个新列表:

If you want to go with the IEqualityComparer<T>you can create a new List from the second list:

  var secondListA = CollectionB.Select(x=> new A(){Category=x.Category, recId=x.recId});

然后创建您的Comparer:

sealed class MyComparer : IEqualityComparer<A>
{
    public bool Equals(A x, A y)
    {
        if (x == null)
            return y == null;
        else if (y == null)
            return false;
        else
            return x.recId== y.recId&& x.Category == y.Category;
    }

    public int GetHashCode(A obj)
    {
        return obj.recId.GetHashCode();
    }
}

并使用Except()重载,该重载通过使用指定的IEqualityComparer<T>比较值来产生两个序列的集合差.:

And use Except() overload which produces the set difference of two sequences by using the specified IEqualityComparer<T> to compare values.:

    var result = CollectionA.Except(secondListA, new MyComparer ());

但是我认为您应该使用简单的Where过滤器,因为创建新的A类型列表可能会导致很多性能过高.

But I think you should go with the simple Where filter as creating new List of A type can cause lot of performance overhade.

这篇关于使用多个属性上的except过滤列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆