还在为删除集合中的相同项而烦恼吗?

      在项目过程中大家都会遇到这样的需求,去除相同数据项目。不知道大家做多这样的需求没有,把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();

 

结果如下:

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

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

posted @ 2012-09-04 13:49  HeartDawn  阅读(1757)  评论(8编辑  收藏  举报