【问题标题】:Intersect LINQ query相交 LINQ 查询
【发布时间】:2010-03-04 16:48:17
【问题描述】:

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

也就是说,这能做到吗?

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

其中 original 是 IEnumerable&lt;ClassA&gt;,idsToFind 是 IEnumerable&lt;long&gt;

【问题讨论】:

    标签: c# .net linq


    【解决方案1】:

    是的。

    正如其他人回答的那样,您可以使用Where,但是对于大型集合来说效率非常低。

    如果您担心性能问题,您可以致电Join

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

    如果idsToFind 可以包含重复项,您需要在ID 或结果上调用Distinct(),或者将Join 替换为GroupJoin(GroupJoin 的参数将相同)。

    【讨论】:

    • 这就是我要找的,谢谢。不知何故,这并没有出现在我原来的问题中,而是 idsToFind = IEnumerable。再次感谢。
    • 知道originalidsToFind 的哪个大小,Join 开始变得比Where/Contains 解决方案更有效吗?我可以想象对于小列表(可能是 20-30 项)Join 有太多开销?
    • 有帮助,可以使用这个依赖Join的扩展方法:stackoverflow.com/a/59321033/1248177
    【解决方案2】:

    我将使用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));
    

    【讨论】:

      【解决方案3】:

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

      var results = original.Where(x => yourEnumerable.Contains(x.ID));
      

      另一方面,Intersect 会找到两个IEnumerable 中的元素。如果您只是在寻找 ID 列表,您可以执行以下操作,利用 Intersect

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

      【讨论】:

        【解决方案4】:

        一个简单的方法是:

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

        【讨论】:

          【解决方案5】:

          使用Where方法过滤结果:

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

          【讨论】:

            【解决方案6】:

            命名事物很重要。下面是一个基于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 =&gt; item.id)

            【讨论】:

              【解决方案7】:

              我整个上午都在玩 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();
              

              这似乎按预期工作,没有任何显着的性能差异,实际上并不比第一个复杂。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2014-12-25
                • 2012-03-07
                • 1970-01-01
                • 2013-05-07
                • 2020-10-31
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多