C# 集合交、並、差、去重,物件集合交併差

古兆洋發表於2024-11-15

轉自: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

樹立目標,保持活力,gogogo!

相關文章