C# 實現Distinct將物件按條件去重
平時,我們將c#中的Distinct大多用於對陣列去重,一般陣列為基礎的資料型別,例如 int,string.也可以用於物件去重,我們看看C#對Distinct方法的定義:
有過載,第一個引數都加了this,是拓展方法,有關拓展方法,請百度瞭解。
下面我們來研究下Distinct的物件去重,假設我們現在有一個People類:
public class People { public int ID { get; set; } /// <summary> /// 姓名 /// </summary> public string Name { get; set; } /// <summary> /// 所屬省份 /// </summary> public string Province { get; set; } /// <summary> /// 年齡 /// </summary> public int Age { get; set; } public override string ToString() { return string.Format("ID:{0} Name:{1} Province:{2} Age:{3}",ID,Name,Province,Age); } }
我們宣告一個ListPeole物件集合:
People p = new People() { ID = 100,Name = "liu",Province = "廣東",Age = 100 }; People p1 = p; People p2 = p1; IEnumerable<People> ListPeople = new List<People>() { p,p1,p2,new People(){ID=0,Name="li",Province="湖北",Age=20},new People(){ID=1,Province="湖南",new People(){ID=2,new People(){ID=3,Age=21},new People(){ID=4,Age=22},};
我們來對ListPeople使用Distinct方法,不帶任何引數,執行結果如下:
可以看到,Distinct方法沒有帶引數的話,將物件集合中p,p2進行去重,而對於物件的成員值是一樣的不同物件沒有去重,說明Distinct方法不加引數的話,去重的規則是比較物件集合中物件的引用是否相同,如果相同,則去重,否則不去重。
現在我們有個需求,對於ID相同的People,我們算做同一個人,要輸出集合中不重複的人(對於ID相同的隨便輸出一個即可),這時,我們用到了Distinct的第二個方法,方法要求傳入的引數是IEqualityComparer型別,繼承一個泛型介面,我們加入如下程式碼:
public class PeopleCompareByID : IEqualityComparer<People> { public bool Equals(People x,People y) { if (x == null || y == null) return false; if (x.ID == y.ID) return true; else return false; } public int GetHashCode(People obj) { if (obj == null) return 0; else return obj.ID.GetHashCode(); } }
繼承IEqualityComparer介面必須實現Equals和GetHashCode方法。
我們比較的時候,傳入一個PeopleCompareByID 的實體即可:
ListPeople.Distinct(new PeopleCompareByID()).ToList().ForEach(x => Console.WriteLine(x));
執行結果如下:
達到了我們以ID去重的效果。
現在需求又變,ID和省份相同的算同一個人,要輸出人的資訊(相同的隨便輸出一個即可),這個時候,我們看到ID=0和Province="湖北"的存在重複,要將其去重,我們再來一個類,還是繼承自IEqualityComparer:
public class PeopleCompareByIDAndProvince : IEqualityComparer<People> { public bool Equals(People x,People y) { if (x == null || y == null) return false; if (x.ID == y.ID&&x.Province==y.Province) return true; else return false; } public int GetHashCode(People obj) { if (obj == null) return 0; else return obj.ID.GetHashCode()^obj.Province.GetHashCode(); } }
同樣,使用Distinct方法的時候,傳入PeopleCompareByIDAndProvince 的例項:
ListPeople.Distinct(new PeopleCompareByIDAndProvince()).ToList().ForEach(x => Console.WriteLine(x));
執行後的結果如下:
新增:1.類的某個屬性是list陣列,按照這個list的引用是否相同來判斷是否是同一個物件
我們再來修改一下上面的程式碼如下:
class Program { static void Main(string[] args) { List<int> list = new List<int>() { 1,2,11,222,3,4 }; List<int> list1 = new List<int>() { 1,4 }; People p1 = new People() { Name = "Tony1",ID = 1,Age = 18,Members = list }; People p2 = new People() { Name = "Tony2",ID = 2,Age = 19,Members = list }; People p3 = new People() { Name = "Tony3",ID = 3,Age = 20,Members = list1 }; People p4 = new People() { Name = "Tony4",ID = 4,Age = 21,Members = new List<int>() }; List<People> personList = new List<People>() { p1,p3,p4 }; personList.Distinct(new PeopleComparedByList()).ToList().ForEach(x => Console.WriteLine(x)); Console.Read(); } } public class People { public int ID { get; set; } /// <summary> /// 姓名 /// </summary> public string Name { get; set; } /// <summary> /// 所屬省份 /// </summary> public string Province { get; set; } /// <summary> /// 年齡 /// </summary> public int Age { get; set; } private List<int> members = new List<int>(); public List<int> Members { get { return members; } set { members = value; } } public override string ToString() { return string.Format("ID:{0} Name:{1} Province:{2} Age:{3},Members:{4}",Age,string.Join("-",this.Members.ToList())); } } public class PeopleComparedByList : IEqualityComparer<People> { public bool Equals(People x,People y) { if (x.Members == y.Members) return true; else return false; } public int GetHashCode(People obj) { return obj.Members.GetHashCode(); } }
執行的結果如下:
從結果可以看到,Tony1,Tony2的Members屬性是一個同一個引用的list,所以去重複的時候把Tony2給去掉了
達到了我們想要的效果。
新增:2.類的某個屬性是list陣列,按照這個list的各元素的值是否相同來判斷是否是同一個物件
我們來新增加一個比較器:
public class PeopleComparedByListValue : IEqualityComparer<People> { public bool Equals(People x,People y) { if (x.Members == null && y.Members == null) return true; if (x.Members == null || y.Members == null) return false; if (x.Members.Count != y.Members.Count) return false; //迴圈比較值 for (int i = 0; i < x.Members.Count; i++) { if (x.Members[i] != y.Members[i]) return false; } return true; } public int GetHashCode(People obj) { var hashCode = 1; if (obj.Members == null) return 0; if (obj.Members.Count == 0) return 1; obj.Members.ForEach(x => hashCode ^= x); return hashCode; } }
使用這個比較器:
static void Main(string[] args) { List<int> list = new List<int>() { 1,p4 }; personList.Distinct(new PeopleComparedByListValue()).ToList().ForEach(x => Console.WriteLine(x)); Console.Read(); }
執行結果:
可以看到,陣列值為1,4 的只剩下一個了,達到了按值相同去重複的效果。
以後遇到以三個或者四個甚至更多的物件成員來決定物件是否重複的去重問題時,可以採用這種方法。
以上為個人拙見。這篇C# 實現Distinct將物件按條件去重就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。