zoukankan      html  css  js  c++  java
  • 还在为删除集合中的相同项而烦恼吗?

          在项目过程中大家都会遇到这样的需求,去除相同数据项目。不知道大家做多这样的需求没有,把csv数据导入到DB中。要求csv中如果某几个列相同,这样的数据就不插入到库中。
    第一个闪现在大家脑海中的方法是不是直接写个循环,然后一个个去判断。今天我们来看看另一套方法。利用Distinct方法来进行实现。
          我们来看看这个方法,这个方法来之Enumerable这个静态类,里面有这样一个方法
          public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer);
    这个方法是一个扩展方法。在形参里面有两个参数,大家有没有看到第一个形参中有个this,其实这就是扩展方法。在这里给大家稍微温习下扩展方法,
    扩展方法是编译器的一种手段。它需要几个条件
    1、在静态类中

    2、是一个静态的公共的方法

    3、第一个形参前要加上一个this


    这样就可以了。你要扩展到哪个类中去,那么第一个参数就是那个类的类型。

    我们再来看看第二个参数IEqualityComparer<TSource> comparer是一个IEqualityComparer<TSource>的泛型接口。
    我们看看这个泛型接口,这个接口里面只有两个方法
           bool Equals(T x, T y);
           int GetHashCode(T obj);
    我们来看看Equals,从解释中我们知道。如果两个对象是相等的就返回true,如果不相等就返回false。

    好的,那我们就来构造集合中的Distinct方法需要的条件。
    首先我们来实现我们自己的比较类,然后再来实现这个接口。
    我们这个类的需求是这样的。可以自定设定要比较的属性名,可以是多个也可是是单个。

    分析就到这里,接下来我们来看看具体的实现方式
    请看代码:

    View Code
     1 /// <summary>
     2     /// 消除集合中的相同的对象
     3     /// </summary>
     4     /// <typeparam name="T"></typeparam>
     5     public class DistinctObj<T> : IEqualityComparer<T>
     6     {
     7         /// <summary>
     8         /// 相同的属性名集合
     9         /// </summary>
    10         private List<string> lstPropertyName = new List<string>();
    11 
    12         /// <summary>
    13         /// 设置属性集合
    14         /// </summary>
    15         /// <param name="propertyNameArr">属性集合数组</param>
    16         public void SetCompareProperty(params string[] propertyNameArr) 
    17         {
    18             lstPropertyName.AddRange(propertyNameArr);
    19         }
    20 
    21         #region IEqualityComparer<T> Member
    22 
    23         public bool Equals(T x, T y)
    24         {
    25             Type t = typeof(T);
    26             
    27             List<object> lstProperty1Value = new List<object>();
    28             List<object> lstProperty2Value = new List<object>();
    29 
    30             foreach (string propertyName in this.lstPropertyName)
    31             {
    32                 object value1 = t.GetProperty(propertyName).GetValue(x, null);
    33                 object value2 = t.GetProperty(propertyName).GetValue(y, null);
    34 
    35 
    36                 // 同时为空的时候,在比较的时候会报错,这里给其自动设置默认值
    37                 string guid = Guid.NewGuid().ToString();
    38                 if (value1 == null) 
    39                 {
    40                     value1 = guid;
    41                 }
    42 
    43                 if (value2 == null) 
    44                 {
    45                     value2 = guid;
    46                 }
    47 
    48                 lstProperty1Value.Add(value1);
    49                 lstProperty2Value.Add(value2);
    50             }
    51 
    52             bool isTrue = false;
    53 
    54             int equalCount = 0;
    55 
    56             for (int index = 0; index < lstProperty1Value.Count; index++)
    57             {
    58                 if (lstProperty1Value[index].Equals(lstProperty2Value[index])) 
    59                 {
    60                     equalCount++;
    61                 }
    62             }
    63 
    64             if (equalCount == lstProperty2Value.Count)
    65             {
    66                 isTrue = true;
    67             }
    68 
    69             return isTrue;
    70         }
    71 
    72         public int GetHashCode(T obj)
    73         {
    74             return 0;
    75         }
    76 
    77         #endregion
    78     }

    具体代码就如上面所示,代码很简单,就是接受了要比较的对象名。然后比较这个对象的是否相等。

    如果大家有啥不明白的地方就回复下,我第一时间给大家解释。

    接下来,我们来看看调用方式和显示结果。

    测试代码如下:

    View Code
     1 public class Student {
     2 
     3             public string StuNo { get; set; }
     4 
     5             public string StuName { get; set; }
     6 
     7             public string StuTel { get; set; }
     8 
     9             public Student(string no,string name,string tel)
    10             {
    11                 this.StuNo = no;
    12                 this.StuName = name;
    13                 this.StuTel = tel;
    14             }
    15         }
    16 
    17 
    18 List<Student> lstStu = new List<Student>(){
    19                 new Student("0001","","137"),
    20                 new Student("0001","","138"),
    21                 new Student("0002","","137"),
    22                 new Student("0001","","138"),
    23                 new Student("0002","","137"),
    24                 new Student("0003","","137"),
    25                 new Student("0001","","137"),
    26                 new Student("0008","","136"),
    27                 new Student("0008","","137")
    28             };
    29 
    30             Console.WriteLine("未删除重复前..............");
    31             foreach (Student student in lstStu)
    32             {
    33                 Console.WriteLine("No " + student.StuNo + " Name " + student.StuName + "  Tel " + student.StuTel);
    34             }
    35 
    36             DistinctObj<Student> distinct = new DistinctObj<Student>();
    37             distinct.SetCompareProperty(new string[] { "StuNo", "StuTel" });
    38 
    39             List<Student> lst = lstStu.Distinct(distinct).ToList();
    40             Console.WriteLine("删除重复后..............");
    41             foreach (Student student in lst)
    42             {
    43                 Console.WriteLine("No " + student.StuNo + " Name " + student.StuName + "  Tel " + student.StuTel);
    44             }
    45 
    46             Console.Read();

    结果如下:

    不好意思啊。我这里是日文的操作系统。那几个中文字显示的不到位啊。不过不影响大家看效果啊。

    广纳各位的意见。欢迎大家拍砖。

  • 相关阅读:
    Stack集合 Queue队列集合 Hashtable哈希表
    冒泡排序
    2017-3-1 数组
    2017-2-26 三大类知识
    2017-2-25 练习题总结
    2017-2-25 循环语句 跳转语句 迭代法 穷举法 异常语句
    2017-2-22 if语句 if语句的嵌套 以及课堂练习 经典猜拳游戏,闰年判断,输出当前时间的天数等
    2017-2-20 运算符
    2017-2-18 net 输入输出语句
    【Ebola】python day3
  • 原文地址:https://www.cnblogs.com/heardawn/p/2670299.html
Copyright © 2011-2022 走看看