【发布时间】:2013-01-10 16:16:18
【问题描述】:
如何从 2 个不同的列表中提取找到以下表达式的所有元素
List1.id = List2.id && List1.CategoryId = list2.CategoryId
以及如何通过提取主列表中缺少的元素来进行逆操作
!(List1.id = List2.id && List1.CategoryId = list2.CategoryId)
【问题讨论】:
如何从 2 个不同的列表中提取找到以下表达式的所有元素
List1.id = List2.id && List1.CategoryId = list2.CategoryId
以及如何通过提取主列表中缺少的元素来进行逆操作
!(List1.id = List2.id && List1.CategoryId = list2.CategoryId)
【问题讨论】:
您可以为您的数据类型实现一个简单的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);
}
}
【讨论】:
SelectMany 完成的(在第一个查询选择对之前,您也无法使用Except 来适应它)。
Intersect 仅在两个列表的类型相同时才有效,即使使用自定义比较器也是如此。您不能使用它来加入具有不同编译时间类型的两个列表。
Join,则可以完全忽略这个问题,因为从概念上讲,这就是内连接的定义。
所以第一种情况是你的基本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);
}
}
【讨论】:
您也可以使用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();
【讨论】: