在項目過程中大家都會遇到這樣的需求,去除相同數據項目。不知道大家做多這樣的需求沒有,把csv數據導入到DB中。要求csv中如果某幾個列相同,這樣的數據就不插入到庫中。
第一個閃現在大家腦海中的方法是不是直接寫個循環,然后一個個去判斷。今天我們來看看另一套方法。利用Distinct方法來進行實現。
我們來看看這個方法,這個方法來之Enumerable這個靜態類,里面有這樣一個方法
public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer);
這個方法是一個擴展方法。在形參里面有兩個參數,大家有沒有看到第一個形參中有個this,其實這就是擴展方法。在這里給大家稍微溫習下擴展方法,
擴展方法是編譯器的一種手段。它需要幾個條件
1、在靜態類中
2、是一個靜態的公共的方法
3、第一個形參前要加上一個this
這樣就可以了。你要擴展到哪個類中去,那么第一個參數就是那個類的類型。
我們再來看看第二個參數IEqualityComparer<TSource> comparer是一個IEqualityComparer<TSource>的泛型接口。
我們看看這個泛型接口,這個接口里面只有兩個方法
bool Equals(T x, T y);
int GetHashCode(T obj);
我們來看看Equals,從解釋中我們知道。如果兩個對象是相等的就返回true,如果不相等就返回false。
好的,那我們就來構造集合中的Distinct方法需要的條件。
首先我們來實現我們自己的比較類,然后再來實現這個接口。
我們這個類的需求是這樣的。可以自定設定要比較的屬性名,可以是多個也可是是單個。
分析就到這里,接下來我們來看看具體的實現方式
請看代碼:

1 /// <summary> 2 /// 消除集合中的相同的對象 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 public class DistinctObj<T> : IEqualityComparer<T> 6 { 7 /// <summary> 8 /// 相同的屬性名集合 9 /// </summary> 10 private List<string> lstPropertyName = new List<string>(); 11 12 /// <summary> 13 /// 設置屬性集合 14 /// </summary> 15 /// <param name="propertyNameArr">屬性集合數組</param> 16 public void SetCompareProperty(params string[] propertyNameArr) 17 { 18 lstPropertyName.AddRange(propertyNameArr); 19 } 20 21 #region IEqualityComparer<T> Member 22 23 public bool Equals(T x, T y) 24 { 25 Type t = typeof(T); 26 27 List<object> lstProperty1Value = new List<object>(); 28 List<object> lstProperty2Value = new List<object>(); 29 30 foreach (string propertyName in this.lstPropertyName) 31 { 32 object value1 = t.GetProperty(propertyName).GetValue(x, null); 33 object value2 = t.GetProperty(propertyName).GetValue(y, null); 34 35 36 // 同時為空的時候,在比較的時候會報錯,這里給其自動設置默認值 37 string guid = Guid.NewGuid().ToString(); 38 if (value1 == null) 39 { 40 value1 = guid; 41 } 42 43 if (value2 == null) 44 { 45 value2 = guid; 46 } 47 48 lstProperty1Value.Add(value1); 49 lstProperty2Value.Add(value2); 50 } 51 52 bool isTrue = false; 53 54 int equalCount = 0; 55 56 for (int index = 0; index < lstProperty1Value.Count; index++) 57 { 58 if (lstProperty1Value[index].Equals(lstProperty2Value[index])) 59 { 60 equalCount++; 61 } 62 } 63 64 if (equalCount == lstProperty2Value.Count) 65 { 66 isTrue = true; 67 } 68 69 return isTrue; 70 } 71 72 public int GetHashCode(T obj) 73 { 74 return 0; 75 } 76 77 #endregion 78 }
具體代碼就如上面所示,代碼很簡單,就是接受了要比較的對象名。然后比較這個對象的是否相等。
如果大家有啥不明白的地方就回復下,我第一時間給大家解釋。
接下來,我們來看看調用方式和顯示結果。
測試代碼如下:

1 public class Student { 2 3 public string StuNo { get; set; } 4 5 public string StuName { get; set; } 6 7 public string StuTel { get; set; } 8 9 public Student(string no,string name,string tel) 10 { 11 this.StuNo = no; 12 this.StuName = name; 13 this.StuTel = tel; 14 } 15 } 16 17 18 List<Student> lstStu = new List<Student>(){ 19 new Student("0001","一","137"), 20 new Student("0001","二","138"), 21 new Student("0002","三","137"), 22 new Student("0001","四","138"), 23 new Student("0002","五","137"), 24 new Student("0003","六","137"), 25 new Student("0001","七","137"), 26 new Student("0008","八","136"), 27 new Student("0008","九","137") 28 }; 29 30 Console.WriteLine("未刪除重復前.............."); 31 foreach (Student student in lstStu) 32 { 33 Console.WriteLine("No " + student.StuNo + " Name " + student.StuName + " Tel " + student.StuTel); 34 } 35 36 DistinctObj<Student> distinct = new DistinctObj<Student>(); 37 distinct.SetCompareProperty(new string[] { "StuNo", "StuTel" }); 38 39 List<Student> lst = lstStu.Distinct(distinct).ToList(); 40 Console.WriteLine("刪除重復后.............."); 41 foreach (Student student in lst) 42 { 43 Console.WriteLine("No " + student.StuNo + " Name " + student.StuName + " Tel " + student.StuTel); 44 } 45 46 Console.Read();
結果如下:
不好意思啊。我這里是日文的操作系統。那幾個中文字顯示的不到位啊。不過不影響大家看效果啊。
廣納各位的意見。歡迎大家拍磚。