还在为删除集合中的相同项而烦恼吗?
在项目过程中大家都会遇到这样的需求,去除相同数据项目。不知道大家做多这样的需求没有,把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方法需要的条件。
首先我们来实现我们自己的比较类,然后再来实现这个接口。
我们这个类的需求是这样的。可以自定设定要比较的属性名,可以是多个也可是是单个。
分析就到这里,接下来我们来看看具体的实现方式
请看代码:
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 }
具体代码就如上面所示,代码很简单,就是接受了要比较的对象名。然后比较这个对象的是否相等。
如果大家有啥不明白的地方就回复下,我第一时间给大家解释。
接下来,我们来看看调用方式和显示结果。
测试代码如下:
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();
结果如下:
不好意思啊。我这里是日文的操作系统。那几个中文字显示的不到位啊。不过不影响大家看效果啊。
广纳各位的意见。欢迎大家拍砖。