使用LINQ在特定属性上对对象进行相交和除 [英] Using LINQ to objects Intersect and Except on a specific property

查看:72
本文介绍了使用LINQ在特定属性上对对象进行相交和除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我有2个List<string>对象时,可以直接在它们上使用IntersectExcept以获得输出IEnumerable<string>.这很简单,但是如果我想在更复杂的事物上进行交集/分离,该怎么办?

When I have 2 List<string> objects, then I can use Intersect and Except on them directly to get an output IEnumerable<string>. That's simple enough, but what if I want the intersection/disjuction on something more complex?

例如,尝试获取ClassA对象的集合,这是ClassA对象的AStr1ClassB对象的BStr相交的结果; :

Example, trying to get a collection of ClassA objects which is the result of the intersect on ClassA object's AStr1 and ClassB object's BStr; :

public class ClassA {
    public string AStr1 { get; set; }
    public string AStr2 { get; set; }
    public int AInt { get; set; }
}
public class ClassB {
    public string BStr { get; set; }
    public int BInt { get; set; }
}
public class Whatever {
    public void xyz(List<ClassA> aObj, List<ClassB> bObj) {
        // *** this line is horribly incorrect ***
        IEnumberable<ClassA> result =
            aObj.Intersect(bObj).Where(a, b => a.AStr1 == b.BStr);
    }
}

如何固定标注的线以实现此交点.

How can I fix the noted line to achieve this intersection.

推荐答案

MoreLINQ 具有 ExceptBy .它还没有IntersectBy,但是您可以轻松编写自己的实现,甚至可以在以后将其贡献给MoreLINQ:)

MoreLINQ has ExceptBy. It doesn't have IntersectBy yet, but you could easily write your own implementation, and possibly even contribute it to MoreLINQ afterwards :)

它可能看起来像 这样(省略错误检查):

It would probably look something like this (omitting error checking):

public static IEnumerable<TSource> IntersectBy<TSource, TKey>(
    this IEnumerable<TSource> first,
    IEnumerable<TSource> second,
    Func<TSource, TKey> keySelector,
    IEqualityComparer<TKey> keyComparer)
{
    HashSet<TKey> keys = new HashSet<TKey>(first.Select(keySelector),
                                           keyComparer);
    foreach (var element in second)
    {
        TKey key = keySelector(element);
        // Remove the key so we only yield once
        if (keys.Remove(key))
        {
            yield return element;
        }
    }
}

如果要对碰巧具有相同属性类型的两种完全不同的类型执行相交,则可以使用三个类型参数(一个用于first,一个用于second,一个用于表示通用密钥类型.

If you wanted to perform an intersection on two completely different types which happened to have a common property type, you could make a more general method with three type parameters (one for first, one for second, and one for the common key type).

这篇关于使用LINQ在特定属性上对对象进行相交和除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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