相交LINQ查询

时间:2010-03-04 16:48:17

标签: c# .net linq

如果我有一个IEnumerable,其中ClassA公开了类型为long的ID属性。 是否可以使用Linq查询来获取具有属于第二个IEnumerable的ID的ClassA的所有实例?

换句话说,这可以吗?

IEnumerable<ClassA> = original.Intersect(idsToFind....)?

其中original是IEnumerable<ClassA>,idsToFind是IEnumerable<long>

7 个答案:

答案 0 :(得分:56)

正如其他人已经回答的那样,您可以使用Where,但对于大型套装来说效率极低。

如果需要考虑表现,可以致电Join

var results = original.Join(idsToFind, o => o.Id, id => id, (o, id) => o);

如果idsToFind可能包含重复内容,则您需要在ID或结果上调用Distinct()或将Join替换为GroupJoin(GroupJoin的参数)会是一样的。)

答案 1 :(得分:15)

我将使用Intersect发布回答。

如果您想要交叉相同类型的2 IEnumerables,这非常有用。

首先,我们需要一个EqualityComparer

    public class KeyEqualityComparer<T> : IEqualityComparer<T>
    {
        private readonly Func<T, object> keyExtractor;

        public KeyEqualityComparer(Func<T, object> keyExtractor)
        {
            this.keyExtractor = keyExtractor;
        }

        public bool Equals(T x, T y)
        {
            return this.keyExtractor(x).Equals(this.keyExtractor(y));
        }

        public int GetHashCode(T obj)
        {
            return this.keyExtractor(obj).GetHashCode();
        }
    }

其次,我们将KeyEqualityComparer应用于Intersect函数:

var list3= list1.Intersect(list2, new KeyEqualityComparer<ClassToCompare>(s => s.Id));

答案 2 :(得分:9)

您可以这样做,但在当前表单中,您需要使用Where扩展方法。

var results = original.Where(x => yourEnumerable.Contains(x.ID));
另一方面,

Intersect会找到IEnumerable的两个元素。如果您只想查找ID列表,可以执行以下操作Intersect

var ids = original.Select(x => x.ID).Intersect(yourEnumerable);

答案 3 :(得分:5)

一种简单的方法是:

IEnumerable<ClassA> result = original.Where(a => idsToFind.contains(a.ID));

答案 4 :(得分:1)

使用Where方法过滤结果:

var result = original.Where(o => idsToFind.Contains(o.ID));

答案 5 :(得分:0)

命名事物很重要。这是基于Join运算符的扩展方法:

private static IEnumerable<TSource> IntersectBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    IEnumerable<TKey> keys,
    Func<TSource, TKey> keySelector)
        => source.Join(keys, keySelector, id => id, (o, id) => o);

您可以像var result = items.IntersectBy(ids, item => item.id)这样使用它。

答案 6 :(得分:0)

我整个上午都在Intersect上绊倒了,由于它是客户端而不是服务器端,因此它在核心3中不再起作用。

然后,从数据库中提取的项目列表中,用户可以选择以要求子代附加到原始列表以获取更多信息的方式显示它们。

工作用途是:

itemList = _context.Item
        .Intersect(itemList)
        .Include(i => i.Notes)
        .ToList();

现在看来有效的是:

itemList = _context.Item
        .Where(item => itemList.Contains(item))
        .Include(i => i.Notes)
        .ToList();

这似乎按预期方式运行,没有明显的性能差异,并且实际上没有第一个复杂。