C# – 使用扩展方法排序
我想排序一个人说的清单
List persons=new List(); persons.Add(new Person("Jon","Bernald",45000.89)); persons.Add(new Person("Mark","Drake",346.89)); persons.Add(new Person("Bill","Watts",456.899));
基于
public enum CompareOptions { ByFirstName, ByLastName, BySalary } public enum SortOrder { Ascending, Descending }
使用lambda表达式排序的方法是什么?
public static List SortPeople(this List lst, CompareOptions opt1,SortOrder ord) { lst.Sort((p,op1,op2)=>{ how to apply lambda expression here}); }
看起来你试图在List
上调用Sort方法,它接受一个Comparison
委托。 这需要一些工作,因为您首先必须定义兼容的比较function。
第一步是根据CompareOptions
值编写比较函数
private static Comparison Create(CompareOptions opt) { switch (opt) { case CompareOptions.ByFirstName: (x,y) => x.FirstName.CompareTo(y.FirstName); case CompareOptions.ByLastName: (x,y) => x.LastName.CompareTo(y.LastName); case CompareOptions.BySalary: (x,y) => x.Salary - y.Salary; default: throw new Exception(); } }
默认情况下,此function将按升序排序。 如果你想让它下降只是否定价值。 所以现在编写SortPeople可以通过以下方式完成
public static List SortPeople( this List list, CompareOptions opt1, SortOrder ord) ) var original = Create(opt1); var comp = original; if( ord == SortOrder.Descending ) { comp = (x,y) => -(orig(x,y)); } list.Sort(comp); }
编辑
在lambda中100%完成的版本
public static List SortPeople( this List list, CompareOptions opt1, SortOrder ord) ) list.Sort( (x,y) => { int comp = 0; switch (opt) { case CompareOptions.ByFirstName: comp = x.FirstName.CompareTo(y.FirstName); case CompareOptions.ByLastName: comp = x.LastName.CompareTo(y.LastName); case CompareOptions.BySalary: comp = x.Salary.CompareTo(y.Salary); default: throw new Exception(); } if ( ord == SortOrder.Descending ) { comp = -comp; } return comp; }); }
你真的需要枚举吗? 我不认为在一个方法中封装你的搜索逻辑比使用linq方法更清晰或更干燥:
persons.OrderBy( p => p.FirstName ); persons.OrderByDescending( p => p.Salary);
等等
为了使其在lambda中工作,表达式需要形成Comparison
签名。 这将需要2个“人”实例。 你可以这样做:
public static void SortPeople( this List lst, CompareOptions opt1,SortOrder ord) { lst.Sort((left, right) => { int result; // left and right are the two Person instances if (opt1 == CompareOptions.Salary) { result = left.Salary.CompareTo(right.Salary); } else { string compStr1, compStr2; if (opt1 == CompareOptions.FirstName) { compStr1 = left.FirstName; compStr2 = right.FirstName; } else { compStr1 = left.LastName; compStr2 = right.LastName; } result = compStr1.CompareTo(compStr2); } if (ord == SortOrder.Descending) result *= -1; return result; }); }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { List persons = new List (); persons.Add(new Person("Jon", "Bernald", 45000.89)); persons.Add(new Person("Mark", "Drake", 346.89)); persons.Add(new Person("Bill", "Watts", 456.899)); persons.SortPeople(CompareOptions.ByFirstName, SortOrder.Ascending); persons.ForEach(p => Console.WriteLine(p.ToString())); persons.SortPeople(CompareOptions.ByFirstName, SortOrder.Descending); persons.ForEach(p => Console.WriteLine(p.ToString())); persons.SortPeople(CompareOptions.ByLastName, SortOrder.Ascending); persons.ForEach(p => Console.WriteLine(p.ToString())); persons.SortPeople(CompareOptions.ByLastName, SortOrder.Descending); persons.ForEach(p => Console.WriteLine(p.ToString())); persons.SortPeople(CompareOptions.BySalary, SortOrder.Ascending); persons.ForEach(p => Console.WriteLine(p.ToString())); persons.SortPeople(CompareOptions.BySalary, SortOrder.Descending); persons.ForEach(p => Console.WriteLine(p.ToString())); Console.ReadLine(); } } public static class Extensions { public static void SortPeople(this List lst, CompareOptions opt1,SortOrder ord){ lst.Sort((Person p1, Person p2) => { switch (opt1) { case CompareOptions.ByFirstName: return ord == SortOrder.Ascending ? p1.FirstName.CompareTo(p2.FirstName) : p2.FirstName.CompareTo(p1.FirstName); case CompareOptions.ByLastName: return ord == SortOrder.Ascending ? p1.LastName.CompareTo(p2.LastName) : p2.LastName.CompareTo(p1.LastName); case CompareOptions.BySalary: return ord == SortOrder.Ascending ? p1.Salary.CompareTo(p2.Salary) : p2.Salary.CompareTo(p1.Salary); default: return 0; } }); } } public class Person { public double Salary { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public Person(string first, string last, double salary) { this.Salary = salary; this.FirstName = first; this.LastName = last; } public override string ToString() { return string.Format("{0} {1} has a salary of {2}", this.FirstName, this.LastName, this.Salary); } } public enum CompareOptions { ByFirstName, ByLastName, BySalary } public enum SortOrder { Ascending, Descending }
}