参考资料:
http://www.cnblogs.com/A_ming/archive/2013/05/24/3097062.html
为了方便,先定义一个 foreach 的扩展方法:
/// <summary> /// 循环执行方法。 /// </summary> /// <typeparam name="TSource">对象类型。</typeparam> /// <param name="enumerable">对象列表。</param> /// <param name="action">方法。</param> public static void ForEach<TSource>(this IEnumerable<TSource> enumerable, Action<TSource> action) { foreach (var item in enumerable) { action(item); } }
去重复:
/// <summary> /// 通过使用相等比较器对值进行比较返回序列中的非重复元素。 /// </summary> /// <remarks> /// 示例1:var query = items.DistinctBy(p => p.Id); /// 示例2:var query = items.DistinctBy(p => new { p.Id, p.Name }); /// </remarks> /// <typeparam name="TSource">集合类型。</typeparam> /// <typeparam name="TKey">比较元素的类型。</typeparam> /// <param name="source">集合。</param> /// <param name="keySelector">相等比较器(即:选择通过哪个元素来比较)。</param> /// <returns>非重复元素的集合。</returns> public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { var seenKeys = new HashSet<TKey>(); return source.Where(element => seenKeys.Add(keySelector(element))); }
使用方法:
例子里通过使用 Person.Id 来做为对象的标识,所以,会过虑掉该集合中重复 ID 的元素。
即:返回结果里 ID = 2 的两个元素被去掉一个了。
internal class Program { private static void Main(string[] args) { var items = new List<Person> { new Person {Id = 1, Name = "1111"}, new Person {Id = 2, Name = "2222"}, new Person {Id = 2, Name = "2222"}, new Person {Id = 3, Name = "3333"} }; var query = items.DistinctBy(item => item.Id); query.ForEach(item => Console.WriteLine("id={0},name={1}", item.Id, item.Name)); Console.Read(); } } public class Person { public int Id { get; set; } public string Name { get; set; } }
交集:
/// <summary> /// 通过使用相等比较器对值进行比较生成两个序列的差集。 /// </summary> /// <remarks> /// 即:返回所有属于 source 集合且不属于 target 集合的元素构成的集合。 /// 示例1:var query = items1.ExceptBy(items2, item => item.Id); /// 示例2:var query = items.ExceptBy(items2, p => new { p.Id, p.Name }); /// </remarks> /// <typeparam name="TSource">集合类型。</typeparam> /// <typeparam name="TKey">比较元素的类型。</typeparam> /// <param name="source">源集合。</param> /// <param name="target">过虑集合。</param> /// <param name="keySelector">相等比较器(即:选择通过哪个元素来比较)。</param> /// <returns>source 集合与 target 集合的差集。</returns> public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> source, IEnumerable<TSource> target, Func<TSource, TKey> keySelector) { var seenTargets = new HashSet<TKey>(); target.ForEach(item => seenTargets.Add(keySelector(item))); var result = source.Where(element => { var added = seenTargets.Add(keySelector(element)); if (added) { seenTargets.Remove(keySelector(element)); } return added; }); return result; }
使用方法:
例子里通过使用 Person.Id 来做为对象的标识,所以,会过虑掉两个集合中都存在相同 ID 的元素。
即:返回结果里 ID = 1 的元素被去掉了。
internal class Program { private static void Main(string[] args) { var items = new List<Person> { new Person {Id = 1, Name = "1111"}, new Person {Id = 2, Name = "2222"}, new Person {Id = 2, Name = "2222"}, new Person {Id = 3, Name = "3333"} }; var items2 = new List<Person> { new Person {Id = 1, Name = "1111"} }; var query = items.ExceptBy(items2, item => item.Id); query.ForEach(item => Console.WriteLine("id={0},name={1}", item.Id, item.Name)); Console.Read(); } } public class Person { public int Id { get; set; } public string Name { get; set; } }