【问题标题】:Linq for selecting elements from list 1 that exist on list 2 by comparsion between 2 properties valuesLinq 通过比较 2 个属性值从列表 1 中选择存在于列表 2 中的元素
【发布时间】:2013-01-10 16:16:18
【问题描述】:

如何从 2 个不同的列表中提取找到以下表达式的所有元素

List1.id = List2.id && List1.CategoryId = list2.CategoryId

以及如何通过提取主列表中缺少的元素来进行逆操作

!(List1.id = List2.id && List1.CategoryId = list2.CategoryId)

【问题讨论】:

    标签: c# linq filter


    【解决方案1】:

    您可以为您的数据类型实现一个简单的IComparer 并使用

     var intersection = List1.Intersect(List2, myCategoryIdComparer);
    
     var notRepeating = List1.Union(List2).Except(intersection);
    
     var notInList1 = List2.Except(List1, myCategoryIdComparer);
    

    您可以轻松实现IComparer

     public class CategoryComparer : IComparer  { 
              int IComparerList1.CompareIntersect( Object x, Object y )  {
              // do some type checks to make sure both are CategoryObject
              return ((CategoryObject)x).CategoryID
                  .Compare(((CategoryObject)y).CategoryIdmyCategoryIdComparer);
          } 
      }
    

    【讨论】:

    • 那将无法处理第二种情况
    • 您对第二个的尝试不正确。您需要获取成对的项目,以便您拥有每对不具有相同 ID 值的项目。这是使用SelectMany 完成的(在第一个查询选择对之前,您也无法使用Except 来适应它)。
    • 哦,尚不清楚它是否适用,但Intersect 仅在两个列表的类型相同时才有效,即使使用自定义比较器也是如此。您不能使用它来加入具有不同编译时间类型的两个列表。
    • @Servy 问题中未指定类型。如果这两种类型都有 CategoryID,则 IComparer 可以比较公开其 Category 和 ID 属性的接口。
    • 这就是为什么我说,“不清楚它是否适用”。这可能是一个问题,也可能不是。如果您改用Join,则可以完全忽略这个问题,因为从概念上讲,这就是内连接的定义。
    【解决方案2】:

    所以第一种情况是你的基本Join 操作,Linq 支持:

    var matchingItems = from item1 in list1
                join item2 in list2
                on new{ item1.id, item1.CategoryId} 
                equals new{ item2.id, item2.CategoryId}
                select new { item1, item2 };
    

    对于第二种情况:

    var idValues = list2.Select(item => new { item.id, item.CategoryId })
        .ToHashSet();
    var missingItems = list1.Where(item => !idValues.Contains(new { item.id, item.CategoryId }));
    

    这里是ToHashSet的定义:

    public static class Extensions
    {
        public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source)
        {
            return new HashSet<T>(source);
        }
    }
    

    【讨论】:

    • 这里的问题是你能写多少行来做同样简单的事情
    • 我没明白你的意思。你是说你可以用更少的代码做同样的事情吗?如果是这样,请务必证明。目前你的第一个答案不完整,如果你完成它会比这长得多,而你的第二个答案不起作用,所以比较它们是无效的。
    • 您的答案将是我正在寻找的,因为我提到的那些列表在这种特殊情况下不是同一类型,但在您的最后一个示例中,我得到的项目列表仅存在于两张桌子。基于这个返回的列表,我可以实现一个过滤器来获取 List2 上缺少的项目的返回列表吗?
    【解决方案3】:

    您也可以使用join 子句,尽管它需要您初始化许多匿名类型。

    var result = (from l1 in list1
                  join l2 in list2 on new {l1.Id, l1.Category} 
                  equals new {l2.Id, l2.Category}
                  select l1).ToArray();
    

    【讨论】:

    • 那将无法处理第二种情况
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多