• .NET的求复杂类型集合的差集、交集、并集


    前言

    如标题所述,在ASP.NET应用程序开发中,两个集合做比较时 我们使用微软IEnumerable封装的 Except/Intersect/Union 取 差集/交集/并集 方法是非常的方便的;

    但以上对于不太熟悉的小伙伴来讲,在遇到求包含引用类型(不包含string)集合时就非常的苦恼;

    下面我将带着大家去了解如何通过微软自带方法方式去取**复杂类型集合**的差集、交集、并集。

     

    场景

    这里是场景,我有以下两个学生集合。

    复制代码
    namespace Test2
    {
        internal class Program
        {
            public void Main()
            {
                //列表1
                List StudentList1 = new List()
                {
                      new Student {Id=1,Name="小明",Age=27  },
                      new Student {Id=3,Name="大郭",Age=28  },
                      new Student {Id=4,Name="老登",Age=29  }
                 };
                List StudentList2 = new List()
                {
                     new Student {Id=1,Name="小明",Age=27  },
                     new Student {Id=3,Name="大郭",Age=28  },
                     new Student {Id=4,Name="老登",Age=29 },
                     new Student {Id=4,Name="小路",Age=28 },
                     new Student {Id=4,Name="小明",Age=30 }
                 };
    
            }
        }
    }
    复制代码

     

     生成两个实体集合;

     

    下面我们取交集/差集/并集

     

    完整调用示例(.NET Core):

    复制代码
    namespace Test2
    {
        internal class Program
        {
            public static void Main()
            {
                //列表1
                List StudentList1 = new List()
                {
                      new Student {Id=1,Name="小明",Age=27  },
                      new Student {Id=2,Name="大郭",Age=28  },
                      new Student {Id=3,Name="老登",Age=29  }
                 };
                //列表2
                List StudentList2 = new List()
                {
                     new Student {Id=1,Name="小明",Age=27  },
                     new Student {Id=2,Name="大郭",Age=28  },
                     new Student {Id=3,Name="老登",Age=29 },
                     new Student {Id=4,Name="小路",Age=28 },
                     new Student {Id=5,Name="小明",Age=30 }
    
                 };
                //取比列表1里多出来的学生数据 并输出
                var ExceptData = StudentList2.Except(StudentList1);
                Console.WriteLine("差集:" + String.Join(";", ExceptData.Select(x => { return $"{x.Id}-{x.Name}-{x.Age}"; })));
    
                //取列表1与列表2里共有的学生数据
                var IntersectData = StudentList1.Intersect(StudentList2);
                Console.WriteLine("交集:" + String.Join(";", IntersectData.Select(x => { return $"{x.Id}-{x.Name}-{x.Age}"; })));
    
                //获取办理所有学生的数据(一个相同的学生只能一条)
                var UnionData = StudentList1.Union(StudentList2);
                Console.WriteLine("并集:"+String.Join(";", UnionData.Select(x => { return $"{x.Id}-{x.Name}-{x.Age}"; })));
    
            }
    
        }
    }
    复制代码

     输出:

      差集:1-小明-27;2-大郭-28;3-老登-29;4-小路-28;5-小明-30
      交集:null
      并集:1-小明-27;2-大郭-28;3-老登-29;1-小明-27;2-大郭-28;3-老登-29;4-小路-28;5-小明-30

    以上输出仔细看一下明显是不对的,这就涉及到了复杂类型对比,请看代码:

    正常我们声明的类

    复制代码
    /// 
    /// 学生类
    /// 
    internal class Student
    {
        /// 
        /// 编号
        /// 
        public int Id { get; set; }
    
        /// 
        /// 姓名
        /// 
        public string Name { get; set; }
    
        /// 
        /// 年龄
        /// 
        public int Age { get; set; }
    
    }
    复制代码

     

     因为我们要对比的是引用类型,因为在对比除string引用类型外,其他引用类型的对比默认都是对比的堆里地址,所以我们要实现一个自定义的对比方案

    我们需要继承一个接口 IEqualityComparer 泛型接口

    如下:(这里我们以年龄与名做为对比条件)

    复制代码
    /// 
    /// 学生类
    /// 
    internal class Student : IEqualityComparer
    {
        /// 
        /// 编号
        /// 
        public int Id { get; set; }
    
        /// 
        /// 姓名
        /// 
        public string Name { get; set; }
    
        /// 
        /// 年龄
        /// 
        public int Age { get; set; }
    
        /// 
        /// 比较器
        /// 
        /// 比较实体1
        /// 比较实体2
        /// 
        public bool Equals(Student s1, Student s2)
        {
            //验证相等条件
            if (s1.Name == s2.Name && s1.Age == s2.Age)
            {
                return true;
            }
            return false;
        }
    
        /// 
        /// 获取唯一条件
        /// 
        /// 
        /// 
        public int GetHashCode(Student stu)
        {
            return (stu.Name + "|" + stu.Age).GetHashCode();
        }
    }
    复制代码

     

    修改了类后还有最重要的一点:就是修改比较的方法(相当于声明一个自定义的比较器给方法)

    复制代码
       //取比列表1里多出来的学生数据 并输出
                var ExceptData = StudentList2.Except(StudentList1,new Student());
                Console.WriteLine("差集:" + String.Join(";", ExceptData.Select(x => { return $"{x.Id}-{x.Name}-{x.Age}"; })));
    
                //取列表1与列表2里共有的学生数据
                var IntersectData = StudentList1.Intersect(StudentList2,new Student());
                Console.WriteLine("交集:" + String.Join(";", IntersectData.Select(x => { return $"{x.Id}-{x.Name}-{x.Age}"; })));
    
                //获取办理所有学生的数据(一个相同的学生只能一条)
                var UnionData = StudentList1.Union(StudentList2,new Student());
                Console.WriteLine("并集:"+String.Join(";", UnionData.Select(x => { return $"{x.Id}-{x.Name}-{x.Age}"; })));
    复制代码

     输出:

      差集:4-小路-28;5-小明-30 

      交集:1-小明-27;2-大郭-28;3-老登-29

      并集:1-小明-27;2-大郭-28;3-老登-29;4-小路-28;5-小明-30

     

    到这里引用类型的比较已经完成了,比较器的条件方法可以根据需求调整,如有不足之处,希望大家多多指正!!!

     

     
     
     
     
     
     
     
     
  • 相关阅读:
    基于MIndSpore框架的道路场景语义分割方法研究
    QToolButton几个小知识点总结
    大厂竞相入局 Rust,性能、安全是关键,揭晓 2021 年 Rust 开发者调查报告
    master theorem公式推导
    Apache JMeter压测工具
    @selector() 与SEL 到底是啥
    Python 内置logging 使用详细讲
    单源最短路的建图
    RPA在跨境电商领域在哪些应用场景?
    内置模板市场,DataEase开源数据可视化分析平台v1.13.0发布
  • 原文地址:https://www.cnblogs.com/wslpf/p/16527639.html