您的位置:首页 > 其它

通用的泛型Icomparer生成类,对类进行排序,最大支持4个字段同时比较

2012-06-07 15:18 453 查看
一,通常我们自己定义一个类,然后对类的集合进行排序,是下面这样的做法

class People
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime Birthday { get; set; }

public override string ToString()
{
return string.Format("{0},{1},{2}", ID, Name, Birthday);
}
}


再定义一个类继承IComparer<People>接口

/// <summary>
/// user define
/// </summary>
class PeopleCompare : IComparer<People>
{
#region IComparer<People>

public int Compare(People x, People y)
{
return Comparer<int>.Default.Compare(x.ID, y.ID);
}

#endregion
}


调用代码:

public static void TestFunc()
{
var peoples = new People[] {
new People{ID = 1,Name = "a123",Birthday = new DateTime(2000,05,01)},
new People{ID = 4,Name = "b123",Birthday = new DateTime(2000,04,01)},
new People{ID = 2,Name = "d123",Birthday = new DateTime(2000,02,01)},
new People{ID = 3,Name = "e123",Birthday = new DateTime(2000,04,01)},
};
Array.Sort(peoples, new PeopleCompare());
peoples.ForEach<People>(p => System.Diagnostics.Debug.WriteLine(p));

}


结果输出如下:

1,a123,2000/05/01 0:00:00
2,d123,2000/02/01 0:00:00
3,e123,2000/04/01 0:00:00
4,b123,2000/04/01 0:00:00


,如果我们又定义了Cat,Monkey等等这样的类,就得每次都写一个类似于PeopleCompare的类,当然你也可以在定义People的时候继承Icomparable接口,本文不讨论。

这样做有大量的重复工作,现在考虑定义一个泛型的方法来创建通用的继承了IComparer的类,并且考虑到类有多个字段,对多个字段的排序也考虑进去。下面的这个类定义了一个最大支持4个字段的ComparerFactory类,一般应用已经足够了。

/// <summary>
/// Common Comaparer Generate Class, supported 4 paramers limitted
/// </summary>
/// <typeparam name="T"></typeparam>
public static class ComparerFactroy<T>
{
public static IComparer<T> Create<V1>(Func<T, V1> keySelector1)
{
return new MyCommonComparer<V1, Object, Object, Object>(keySelector1,Comparer<V1>.Default,null,null,null, null, null, null);
}
public static IComparer<T> Create<V1, V2>(Func<T, V1> keySelector1, Func<T, V2> keySelector2)
{
return new MyCommonComparer<V1, V2, Object, Object>(keySelector1,Comparer<V1>.Default, keySelector2,Comparer<V2>.Default,null,null, null, null);
}
public static IComparer<T> Create<V1, V2, V3>(Func<T, V1> keySelector1, Func<T, V2> keySelector2, Func<T, V3> keySelector3)
{
return new MyCommonComparer<V1, V2, V3, Object>(keySelector1, Comparer<V1>.Default, keySelector2, Comparer<V2>.Default, keySelector3, Comparer<V3>.Default, null,null);
}
public static IComparer<T> Create<V1, V2, V3,V4>(Func<T, V1> keySelector1, Func<T, V2> keySelector2, Func<T, V3> keySelector3, Func<T, V4> keySelector4)
{
return new MyCommonComparer<V1, V2, V3, V4>(keySelector1, Comparer<V1>.Default, keySelector2, Comparer<V2>.Default, keySelector3, Comparer<V3>.Default, keySelector4,Comparer<V4>.Default);
}

class MyCommonComparer<V1,V2,V3,V4> : IComparer<T>
{
Func<T, V1> keySelector1;
Func<T, V2> keySelector2;
Func<T, V3> keySelector3;
Func<T, V4> keySelector4;

IComparer<V1> comparer1;
IComparer<V2> comparer2;
IComparer<V3> comparer3;
IComparer<V4> comparer4;

public MyCommonComparer(Func<T, V1> keySelector1, IComparer<V1> compare1,
Func<T, V2> keySelector2, IComparer<V2> compare2,
Func<T, V3> keySelector3, IComparer<V3> compare3,
Func<T, V4> keySelector4, IComparer<V4> compare4)
{
this.keySelector1 = keySelector1;
this.keySelector2 = keySelector2;
this.keySelector3 = keySelector3;
this.keySelector4 = keySelector4;
this.comparer1 = compare1;
this.comparer2 = compare2;
this.comparer3 = compare3;
this.comparer4 = compare4;
}
#region IComparer<T> メンバ

public int Compare(T x, T y)
{
int retVal = 0;
if (keySelector1 != null)
retVal = comparer1.Compare(keySelector1(x), keySelector1(y));
if (keySelector2 != null && retVal == 0)
retVal = comparer2.Compare(keySelector2(x), keySelector2(y));
if (keySelector3 != null && retVal == 0)
retVal = comparer3.Compare(keySelector3(x), keySelector3(y));
if (keySelector4 != null && retVal == 0)
retVal = comparer4.Compare(keySelector4(x), keySelector4(y));

return retVal;
}

#endregion
}
}


ComparerFactory的Create方法根据你传的类型,创建一个Comparer,Create方法有4个重载,可以对1,2,3,4个字段进行排序。

继续用上面定义的People类测试,使用方法如下:

public static void TestFunc()
{
var peoples = new People[] {
new People{ID = 1,Name = "a123",Birthday = new DateTime(2000,05,01)},
new People{ID = 4,Name = "b123",Birthday = new DateTime(2000,04,01)},
new People{ID = 2,Name = "d123",Birthday = new DateTime(2000,02,01)},
new People{ID = 3,Name = "e123",Birthday = new DateTime(2000,04,01)},
new People{ID = 3,Name = "e123",Birthday = new DateTime(2000,03,01)},
new People{ID = 3,Name = "c123",Birthday = new DateTime(2000,03,01)}
};

Array.Sort(peoples, ComparerFactroy<People>.Create(p => p.ID, p => p.Name, p => p.Birthday));

peoples.ForEach<People>(p => System.Diagnostics.Debug.WriteLine(p));

}


分别根据People的ID,Name,Birthday进行排序

测试结果:

1,a123,2000/05/01 0:00:00
2,d123,2000/02/01 0:00:00
3,c123,2000/03/01 0:00:00
3,e123,2000/03/01 0:00:00
3,e123,2000/04/01 0:00:00
4,b123,2000/04/01 0:00:00


可以继续完善的地方:

1,现在默认是每个字段的升序排列,可以在参数中每个字段的升序降序排列。

2,现在只支持4个字段,扩充字段代码改动较大,不知道还有没有更好的支持多字段的写法,欢迎一起讨论。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐