C# 實現(xiàn)Distinct將對象按條件去重
平時,我們將c#中的Distinct大多用于對數(shù)組去重,一般數(shù)組為基礎的數(shù)據(jù)類型,例如 int,string.也可以用于對象去重,我們看看C#對Distinct方法的定義:

有重載,第一個參數(shù)都加了this,是拓展方法,有關拓展方法,請百度了解。
下面我們來研究下Distinct的對象去重,假設我們現(xiàn)在有一個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=0,Name="li",Province="湖北",Age=20},
new People(){ID=1,Name="li",Province="湖北",Age=20},
new People(){ID=1,Name="li",Province="湖南",Age=20},
new People(){ID=2,Name="li",Province="湖北",Age=20},
new People(){ID=3,Name="li",Province="湖南",Age=21},
new People(){ID=4,Name="li",Province="湖北",Age=22},
};
我們來對ListPeople使用Distinct方法,不帶任何參數(shù),運行結果如下:

可以看到,Distinct方法沒有帶參數(shù)的話,將對象集合中p,p1,p2進行去重,而對于對象的成員值是一樣的不同對象沒有去重,說明Distinct方法不加參數(shù)的話,去重的規(guī)則是比較對象集合中對象的引用是否相同,如果相同,則去重,否則不去重。
現(xiàn)在我們有個需求,對于ID相同的People,我們算做同一個人,要輸出集合中不重復的人(對于ID相同的隨便輸出一個即可),這時,我們用到了Distinct的第二個方法,方法要求傳入的參數(shù)是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接口必須實現(xiàn)Equals和GetHashCode方法。
我們比較的時候,傳入一個PeopleCompareByID 的實體即可:
ListPeople.Distinct(new PeopleCompareByID()).ToList().ForEach(x => Console.WriteLine(x));
運行結果如下:

達到了我們以ID去重的效果。
現(xiàn)在需求又變,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數(shù)組,按照這個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, 2, 11, 222, 3, 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, p2,p2,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}", ID, Name, Province, 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數(shù)組,按照這個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;
//循環(huán)比較值
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, 2, 11, 222, 3, 4 };
List<int> list1 = new List<int>() { 1, 2, 11, 222, 3, 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, p2,p2,p3,p4 };
personList.Distinct(new PeopleComparedByListValue()).ToList().ForEach(x => Console.WriteLine(x));
Console.Read();
}
運行結果:

可以看到,數(shù)組值為1, 2, 11, 222, 3, 4 的只剩下一個了,達到了按值相同去重復的效果。
以后遇到以三個或者四個甚至更多的對象成員來決定對象是否重復的去重問題時,可以采用這種方法。
以上為個人拙見。這篇C# 實現(xiàn)Distinct將對象按條件去重就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
BootStrap mvcpager分頁樣式(get請求,刷新頁面)
這篇文章主要介紹了BootStrap mvcpager分頁樣式(get請求,刷新頁面)的相關資料,通過引入相關文件,實現(xiàn)此功能,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-08-08
C#.net實現(xiàn)在Winform中從internet下載文件的方法
這篇文章主要介紹了C#.net實現(xiàn)在Winform中從internet下載文件的方法,實例分析了基于Winform實現(xiàn)文件下載的相關技巧,需要的朋友可以參考下2015-07-07
C# Winform 調用系統(tǒng)接口操作 INI 配置文件的代碼
封裝了一小段代碼, 調用系統(tǒng)接口, 操作配置文件. 一般用于 .ini 文件, 或者其它鍵值對格式的配置文件2011-05-05

