轉自:https://www.cnblogs.com/hao-1234-1234/p/10408602.html
關鍵詞:C# List 集合 交集、並集、差集、去重, 物件集合、 物件、引用型別、交併差、List<T>
有時候看官網文件是最高效的學習方式!
一、簡單集合
Intersect 交集,Except 差集,Union 並集
int[] oldArray = { 1, 2, 3, 4, 5 };
int[] newArray = { 2, 4, 5, 7, 8, 9 };
var jiaoJi = oldArray.Intersect(newArray).ToList();//2,4,5
var oldChaJi = oldArray.Except(newArray).ToList();//1,3
var newChaJi = newArray.Except(oldArray).ToList();//7,8,9
var bingJi = oldArray.Union(newArray).ToList();//1,2,3,4,5,7,8,9
二、物件集合
Product[] store1 = { new Product { Name = "apple", Code = 9 }, new Product { Name = "orange", Code = 4 } }; Product[] store2 = { new Product { Name = "apple", Code = 9 }, new Product { Name = "lemon", Code = 12 } }; IEnumerable<Product> union =store1.Union(store2,new ProductComparer()); IEnumerable<Product> except=store1.Except(store2,new ProductComparer()); IEnumerable<Product> intersect=store1.Intersect(store2,new ProductComparer()); IEnumerable<Product> distinct=store1.Distinct(store2,new ProductComparer());
小提示:
1:IEnumerable<Product> 可以簡化為 匿名型別 var
對自己去重:
var distinct=store1.Distinct(new ProductComparer());
相對於別人去重
var distinct=store1.Distinct(store2,new ProductComparer());
2: 可以繼續進行一些linq或拉姆達操作
var distinct=store1.Distinct(store2,new ProductComparer()).OrderBy(c=>c.Code);
原因是引用了linq元件:using System.Linq;
三、比較類的實現
public class Product { public string Id {get;set} public string Name { get; set; } public int Code { get; set; } }
1只有一個比較條件
//如果物件存在唯一主鍵,例如:從資料庫裡查詢出來的資料存在 ID class ProductComparer : IEqualityComparer<Product> { // Products are equal if their names and product numbers are equal. public bool Equals(Product x, Product y) { //Check whether the compared objects reference the same data. if (Object.ReferenceEquals(x, y)) return true; //Check whether any of the compared objects is null. if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false; //Check whether the products' properties are equal. return x.ID == y.ID; } // If Equals() returns true for a pair of objects // then GetHashCode() must return the same value for these objects. public int GetHashCode(Product product) { //Check whether the object is null if (Object.ReferenceEquals(product, null)) return 0; //Get hash code for the Code field. int hashID = product.ID.GetHashCode(); //Calculate the hash code for the product. return hashID; } }
2 多個比較條件
// 如果存在組合主鍵或組合唯一索引,即多個欄位組合才能確定唯一性。 // Custom comparer for the Product class class ProductComparer : IEqualityComparer<Product> { // Products are equal if their names and product numbers are equal. public bool Equals(Product x, Product y) { //Check whether the compared objects reference the same data. if (Object.ReferenceEquals(x, y)) return true; //Check whether any of the compared objects is null. if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false; //Check whether the products' properties are equal. return x.Code == y.Code && x.Name == y.Name; } // If Equals() returns true for a pair of objects // then GetHashCode() must return the same value for these objects. public int GetHashCode(Product product) { //Check whether the object is null if (Object.ReferenceEquals(product, null)) return 0; //Get hash code for the Name field if it is not null. int hashProductName = product.Name == null ? 0 : product.Name.GetHashCode(); //Get hash code for the Code field. int hashProductCode = product.Code.GetHashCode(); //Calculate the hash code for the product. return hashProductName ^ hashProductCode; } }
3 難道我們每次都要“簡單重複的”繼承IEqualityComparer介面,來重新實現一個“幾乎完全相同的”的Compare類嗎?
對於只有一個比較條件的簡單情況,我們可以直接對 Distinct、Union、Except、Intersect 進行封裝,簡單通用方法:
來源:C#list去重, https://www.cnblogs.com/hao-1234-1234/p/8855218.html
public class Compare<T, C> : IEqualityComparer<T> { private Func<T, C> _getField; public Compare(Func<T, C> getfield) { this._getField = getfield; } public bool Equals(T x, T y) { return EqualityComparer<C>.Default.Equals(_getField(x), _getField(y)); } public int GetHashCode(T obj) { return EqualityComparer<C>.Default.GetHashCode(this._getField(obj)); } } public static class CommonHelper { /// <summary> /// 自定義Distinct擴充套件方法 /// </summary> /// <typeparam name="T">要去重的物件類</typeparam> /// <typeparam name="C">自定義去重的欄位型別</typeparam> /// <param name="source">要去重的物件</param> /// <param name="getfield">獲取自定義去重欄位的委託</param> /// <returns></returns> public static IEnumerable<T> MyDistinct<T, C>(this IEnumerable<T> source, Func<T, C> getfield) { return source.Distinct(new Compare<T, C>(getfield)); } }
然後這麼使用:store1.MyDistinct(s=>s.Id).ToList();
Id 是用於較的屬性(或欄位),它是可以是任何一個屬性。
4、多個比較條件 的通用方法如何實現?
類似於 store1.MyDistinct(s=>s.Id&&Name).ToList();
四、微軟官方文件
union :https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.enumerable.union?view=netframework-4.8
intersect:https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.enumerable.intersect?view=netframework-4.8
except:https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.enumerable.except?view=netframework-4.8
distinct:https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.enumerable.distinct?view=netframework-4.8
合交併差 核心程式碼是相同的: IEqualityComparer 。
建議在看看文件其它部分,以備後用,文件寫的很棒!
例如:join 某些情況與union等效。
五、交集、並集、差集、補集、對稱差集 示意圖,
後兩者後可以有前三者演變而來。補集可以求差或去重、對稱差集可以先求差、在求並;
參考過的文章
https://www.oschina.net/code/snippet_222150_16997
http://www.cnblogs.com/flywing/p/5912242.html
https://blog.csdn.net/wizblack/article/details/78796557