目录
通用排序功能
1.升序
2.降序
测试
1.测试代码
2.测试结果
本篇文章来分享一下C#如何实现通用的排序功能。在项目中经常会使用到排序的方法,那如何使排序方法更加通用呢?可以通过泛型,接口,委托来实现。
通用排序功能
1.升序
为了方便理解,从基本数据类型(int)进行分析,以冒泡排序为例
/// <summary>
/// 整型数组升序排序(冒泡排序)
/// </summary>
/// <param name="array">数组</param>
public static void OrderByInt(int[] array)
{for (int i = 0; i < array.Length; ++i){for (int j = i + 1; j < array.Length; j++){if (array[i] > array[j]){int temp = array[i];array[i] = array[j];array[j] = temp;}}}
}
如果也要对字符串(string)进行比较,那就可以使用比较方法CompareTo
/// <summary>
/// 整型数组升序排序(冒泡排序)
/// </summary>
/// <param name="array">数组</param>
public static void OrderByInt(int[] array)
{for (int i = 0; i < array.Length; ++i){for (int j = i + 1; j < array.Length; j++){if (array[i].CompareTo(array[j]) > 0){int temp = array[i];array[i] = array[j];array[j] = temp;}}}
}/// <summary>
/// string数组升序排序(冒泡排序)
/// </summary>
/// <param name="array">数组</param>
public static void OrderByString(String[] array)
{for (int i = 0; i < array.Length; ++i){for (int j = i + 1; j < array.Length; j++){if (array[i].CompareTo(array[j]) > 0){String temp = array[i];array[i] = array[j];array[j] = temp;}}}
}
要想更加适用,就可以使用泛型,并使用接口约束,只要提供了比较方法的的类型,就可以进行排序
/// <summary>
/// 任何数据类型数组升序排序(冒泡排序)
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
/// <param name="array">数组</param>
public static void OrderByType<T>(T[] array) where T : IComparable<T>
{for (int i = 0; i < array.Length; ++i){for (int j = i + 1; j < array.Length; j++){if (array[i].CompareTo(array[j]) > 0){T temp = array[i];array[i] = array[j];array[j] = temp;}}}
}
那如果要进行排序的类型是复合数据类型,想要按照该类型指定的属性进行排序,该怎么处理呢?我们可以通过接口来实现属性的比较方法。Student类有一个默认字段(Id)的排序方法,若还想通过Age进行排序,可以通过比较器来实现
/// <summary>
/// 任何数据类型数组,按照该类型指定的属性进行升序排序(冒泡排序)
/// <typeparam name="T">数据类型</typeparam>
/// <param name="array">数组</param>
/// <param name="comparer">比较器</param>
public static void OrderByTypeAndProperty<T>(T[] array, IComparer<T> comparer) where T : IComparable<T>
{for (int i = 0; i < array.Length; ++i){for (int j = i + 1; j < array.Length; j++){if (comparer.Compare(array[i], array[j]) > 0){T temp = array[i];array[i] = array[j];array[j] = temp;}}}
}public class Student : IComparable<Student>
{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }public int CompareTo(Student obj){return Id.CompareTo(obj.Id);}
}public class AgeComparer : IComparer<Student>
{public int Compare(Student x, Student y){return x.Age.CompareTo(y.Age);}
}
此时发现使用接口时,如果要排序的属性不同,则要实现多个方法,代码不够简洁,也不便于维护,而委托就解决了这些问题,注意委托定义在类外
/// <summary>
/// 选择委托
/// 返回数据类型T的属性Tkey的值
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
/// <typeparam name="Tkey">数据类型T的字段</typeparam>
/// <returns>选择的属性</returns>
public delegate TKey SelectHandler<T, TKey>(T t);//注意是写在类外/// <summary>
/// 使用委托对任何数据类型数组进行升序排序
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
/// <typeparam name="Tkey">数据类型T的字段</typeparam>
/// <param name="array">数据类型T的数组</param>
/// <param name="selectHandler">选择委托的对象</param>
public static void OrderBy<T, Tkey>(T[] array, SelectHandler<T, Tkey> selectHandler)where Tkey : IComparable<Tkey>
{for (int i = 0; i < array.Length; ++i){for (int j = i + 1; j < array.Length; ++j){//将委托已经取得数据类型的属性的进行比较if (selectHandler(array[i]).CompareTo(selectHandler(array[j])) > 0){T temp = array[i];array[i] = array[j];array[j] = temp;}}}
}
2.降序
降序排序同理
/// <summary>
/// 使用委托对任何数据类型数组进行降序排序
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
/// <typeparam name="Tkey">数据类型T的字段</typeparam>
/// <param name="array">数据类型T的数组</param>
/// <param name="selectHandler">选择委托的对象</param>
public static void OrderByDescending<T, Tkey>(T[] array, SelectHandler<T, Tkey> selectHandler)where Tkey : IComparable<Tkey>
{for (int i = 0; i < array.Length; ++i){for (int j = i + 1; j < array.Length; ++j){//将委托已经取得数据类型的属性的进行比较if (selectHandler(array[i]).CompareTo(selectHandler(array[j])) < 0){T temp = array[i];array[i] = array[j];array[j] = temp;}}}
}
测试
1.测试代码
using System;
using UnityEngine;namespace SortTest
{/// <summary>/// 选择委托/// 返回数据类型T的属性Tkey的值/// </summary>/// <typeparam name="T">数据类型</typeparam>/// <typeparam name="Tkey">数据类型T的字段</typeparam>/// <returns>选择的属性</returns>public delegate TKey SelectHandler<T, TKey>(T t);//注意是写在类外public class SortTest : MonoBehaviour{private void Start(){//int[]int[] intArray = { 4, 1, 5, 0 };SortTestByType(intArray,(value)=> { return value; });//string[]string[] stringArray = { "2","a","ab","hello","0" };SortTestByType(stringArray, (value) => { return value; });//Student[]Student[] studentArray = {new Student(){ Id=1001,Name="张三",Age=20 },new Student(){ Id=1003,Name="李四",Age=18 },new Student(){ Id=1002,Name="赵六",Age=21 },new Student(){ Id=1000,Name="王五",Age=19 }};SortTestByType(studentArray, (studentArray) => { return studentArray.Id; });SortTestByType(studentArray, (studentArray) => { return studentArray.Name; });SortTestByType(studentArray, (studentArray) => { return studentArray.Age; });}private void SortTestByType<T, Tkey>(T[] array, SelectHandler<T, Tkey> selectHandler)where Tkey : IComparable<Tkey>{Debug.Log(array.GetType()+"测试:");OrderBy(array, selectHandler);PrintSortedArray(array, selectHandler);OrderByDescending(array, selectHandler);PrintSortedArray(array, selectHandler);}private void PrintSortedArray<T, Tkey>(T[] array, SelectHandler<T, Tkey> selectHandler)where Tkey : IComparable<Tkey>{string sortedStr="";for (int i = 0; i < array.Length; i++){sortedStr += selectHandler(array[i]).ToString()+" ";}Debug.Log(sortedStr);}/// <summary>/// 使用委托对任何数据类型数组进行升序排序/// </summary>/// <typeparam name="T">数据类型</typeparam>/// <typeparam name="Tkey">数据类型T的字段</typeparam>/// <param name="array">数据类型T的数组</param>/// <param name="selectHandler">选择委托的对象</param>public static void OrderBy<T, Tkey>(T[] array, SelectHandler<T, Tkey> selectHandler)where Tkey : IComparable<Tkey>{for (int i = 0; i < array.Length; ++i){for (int j = i + 1; j < array.Length; ++j){//将委托已经取得数据类型的属性的进行比较if (selectHandler(array[i]).CompareTo(selectHandler(array[j])) > 0){T temp = array[i];array[i] = array[j];array[j] = temp;}}}}/// <summary>/// 使用委托对任何数据类型数组进行降序排序/// </summary>/// <typeparam name="T">数据类型</typeparam>/// <typeparam name="Tkey">数据类型T的字段</typeparam>/// <param name="array">数据类型T的数组</param>/// <param name="selectHandler">选择委托的对象</param>public static void OrderByDescending<T, Tkey>(T[] array, SelectHandler<T, Tkey> selectHandler)where Tkey : IComparable<Tkey>{for (int i = 0; i < array.Length; ++i){for (int j = i + 1; j < array.Length; ++j){//将委托已经取得数据类型的属性的进行比较if (selectHandler(array[i]).CompareTo(selectHandler(array[j])) < 0){T temp = array[i];array[i] = array[j];array[j] = temp;}}}}}public class Student{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }}
}
2.测试结果
好了,今天的分享到这里就结束啦,希望对你有所帮助~