C# 实现Distinct将对象按条件去重

作者:lishuangquan1987 时间:2023-07-24 17:29:59 

平时,我们将c#中的Distinct大多用于对数组去重,一般数组为基础的数据类型,例如 int,string.也可以用于对象去重,我们看看C#对Distinct方法的定义:

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=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方法,不带任何参数,运行结果如下:

C# 实现Distinct将对象按条件去重

可以看到,Distinct方法没有带参数的话,将对象集合中p,p1,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));

运行结果如下:

C# 实现Distinct将对象按条件去重

达到了我们以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));

运行后的结果如下:

C# 实现Distinct将对象按条件去重

新增: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, 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();
 }
}

运行的结果如下:

C# 实现Distinct将对象按条件去重

从结果可以看到,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, 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();
 }

运行结果:

C# 实现Distinct将对象按条件去重

可以看到,数组值为1, 2, 11, 222, 3, 4 的只剩下一个了,达到了按值相同去重复的效果。

以后遇到以三个或者四个甚至更多的对象成员来决定对象是否重复的去重问题时,可以采用这种方法。

来源:https://blog.csdn.net/lishuangquan1987/article/details/76096022

标签:C#,Distinct,对象,去重
0
投稿

猜你喜欢

  • Android使用GestureOverlayView控件实现手势识别

    2023-03-02 08:46:26
  • Java毕业设计实战之校园一卡通系统的实现

    2022-11-26 06:32:56
  • android studio 3.0 service项目背景音乐实现

    2023-07-03 23:34:36
  • Java经典设计模式之模板方法模式定义与用法示例

    2021-07-09 14:07:49
  • c#中单例类与静态类的区别以及使用场景

    2021-07-21 17:06:30
  • Spring boot实现文件上传功能

    2023-08-01 07:00:02
  • hadoop是什么语言

    2021-06-18 07:02:38
  • java数组元素的引用实例讲解

    2023-12-02 16:40:32
  • PageHelper插件实现一对多查询时的分页问题

    2021-11-05 07:02:34
  • Android App应用启动分析与优化

    2023-06-09 01:08:11
  • JAVASE系统实现抽卡功能

    2023-11-19 19:49:41
  • SQL语句删除和添加外键、主键的方法

    2023-04-16 22:18:35
  • java通过AES生成公钥加密数据ECC加密公钥

    2023-08-04 10:09:53
  • 浅析Java SPI 与 dubbo SPI

    2021-10-23 16:54:12
  • Android handle-message的发送与处理案例详解

    2023-07-21 09:28:13
  • 为Android应用增加渠道信息 自动化不同渠道的打包过程的使用详解

    2022-06-01 11:38:22
  • 7种形式的Android Dialog使用实例

    2023-02-08 19:41:02
  • C#检测上传文件真正类型的方法

    2021-10-28 11:32:59
  • Android自定义Seekbar滑动条 Pop提示跟随滑动按钮滑动

    2021-11-02 20:32:06
  • Spring MVC请求参数接收的全面总结教程

    2023-11-28 19:44:47
  • asp之家 软件编程 m.aspxhome.com