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

有重載,第一個(gè)參數(shù)都加了this,是拓展方法,有關(guān)拓展方法,請(qǐng)百度了解。
下面我們來(lái)研究下Distinct的對(duì)象去重,假設(shè)我們現(xiàn)在有一個(gè)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);
}
}
我們聲明一個(gè)ListPeole對(duì)象集合:
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},
};
我們來(lái)對(duì)ListPeople使用Distinct方法,不帶任何參數(shù),運(yùn)行結(jié)果如下:

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

達(dá)到了我們以ID去重的效果。
現(xiàn)在需求又變,ID和省份相同的算同一個(gè)人,要輸出人的信息(相同的隨便輸出一個(gè)即可),這個(gè)時(shí)候,我們看到ID=0和Province="湖北"的存在重復(fù),要將其去重,我們?cè)賮?lái)一個(gè)類,還是繼承自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方法的時(shí)候,傳入PeopleCompareByIDAndProvince 的實(shí)例:
ListPeople.Distinct(new PeopleCompareByIDAndProvince()).ToList().ForEach(x => Console.WriteLine(x));
運(yùn)行后的結(jié)果如下:

新增:1.類的某個(gè)屬性是list數(shù)組,按照這個(gè)list的引用是否相同來(lái)判斷是否是同一個(gè)對(duì)象
我們?cè)賮?lái)修改一下上面的代碼如下:
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();
}
}
運(yùn)行的結(jié)果如下:

從結(jié)果可以看到,Tony1,Tony2的Members屬性是一個(gè)同一個(gè)引用的list,所以去重復(fù)的時(shí)候把Tony2給去掉了
達(dá)到了我們想要的效果。
新增:2.類的某個(gè)屬性是list數(shù)組,按照這個(gè)list的各元素的值是否相同來(lái)判斷是否是同一個(gè)對(duì)象
我們來(lái)新增加一個(gè)比較器:
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;
}
}
使用這個(gè)比較器:
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();
}
運(yùn)行結(jié)果:

可以看到,數(shù)組值為1, 2, 11, 222, 3, 4 的只剩下一個(gè)了,達(dá)到了按值相同去重復(fù)的效果。
以后遇到以三個(gè)或者四個(gè)甚至更多的對(duì)象成員來(lái)決定對(duì)象是否重復(fù)的去重問(wèn)題時(shí),可以采用這種方法。
以上為個(gè)人拙見。這篇C# 實(shí)現(xiàn)Distinct將對(duì)象按條件去重就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
BootStrap mvcpager分頁(yè)樣式(get請(qǐng)求,刷新頁(yè)面)
這篇文章主要介紹了BootStrap mvcpager分頁(yè)樣式(get請(qǐng)求,刷新頁(yè)面)的相關(guān)資料,通過(guò)引入相關(guān)文件,實(shí)現(xiàn)此功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08
C#對(duì)Access進(jìn)行增刪改查的完整示例
本文主要是講C#對(duì)Access數(shù)據(jù)庫(kù)的增刪改查操作,想學(xué)習(xí)C#和Access數(shù)據(jù)庫(kù)操作基礎(chǔ)的可以參考借鑒,以下代碼都經(jīng)過(guò)實(shí)踐測(cè)試可用,下面跟著小編一起來(lái)看看。2016-08-08
C#.net實(shí)現(xiàn)在Winform中從internet下載文件的方法
這篇文章主要介紹了C#.net實(shí)現(xiàn)在Winform中從internet下載文件的方法,實(shí)例分析了基于Winform實(shí)現(xiàn)文件下載的相關(guān)技巧,需要的朋友可以參考下2015-07-07
C#實(shí)現(xiàn)關(guān)機(jī)重啟及注銷實(shí)例代碼
這篇文章主要介紹了C#實(shí)現(xiàn)關(guān)機(jī)重啟及注銷實(shí)例代碼,適合新手參考學(xué)習(xí)之用,需要的朋友可以參考下2014-07-07
C# Winform 調(diào)用系統(tǒng)接口操作 INI 配置文件的代碼
封裝了一小段代碼, 調(diào)用系統(tǒng)接口, 操作配置文件. 一般用于 .ini 文件, 或者其它鍵值對(duì)格式的配置文件2011-05-05

