【问题标题】:C# - Sorting using Extension MethodC# - 使用扩展方法排序
【发布时间】:2010-12-22 02:42:55
【问题描述】:

我想对一个人说的列表进行排序

List<Person> persons=new List<Person>();
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<Person> SortPeople(this List<Person> lst, 
   CompareOptions opt1,SortOrder ord)

        {
           lst.Sort((p,op1,op2)=>{ how to apply lambda expression here});
        }

【问题讨论】:

  • 好问题。您正在使专家生成紧凑且可读的代码。我们都从中学习。谢谢!!
  • @Shahkalpesh ,你也很好地帮助了我的老问题。我想借此机会再次感谢你。

标签: c# extension-methods


【解决方案1】:

您似乎正在尝试调用 List&lt;T&gt; 上的 Sort 方法,该方法采用 Comparison&lt;T&gt; 委托。这将需要一些工作,因为您首先必须定义一个兼容的比较函数。

第一步是写一个基于CompareOptions值的比较函数

private static Comparison<Person> 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();
  }
}

默认情况下,此函数将按升序排序。如果您希望它下降,只需否定该值。所以现在写SortPeople可以通过以下方式完成

public static List<Person> SortPeople(
   this List<Person> 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<Person> SortPeople(
   this List<Person> 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;
   });
}

【讨论】:

  • 这很好,很干净,但它并没有真正展示如何在 lambda 中做到这一点,这是 OP 要求的。
  • @Reed Copsey 我不建议只用一个 Lamba 来做,因为每次比较都会跨越所有的 if,而不是一次选择要使用的正确 lambda。
  • @Reed,是的,我更新了答案以包含纯 lambda 版本。
  • 哦,我同意 - 正如我所说,这是非常干净的(第一个,未经编辑的),但问题是具体如何在那里做......
  • @Jared:这不需要休息吗?开关里面?这段代码我没试过。
【解决方案2】:

你真的需要枚举吗?我不认为将您的搜索逻辑封装在一个方法中比仅使用 linq 方法更清晰或更干:

persons.OrderBy( p => p.FirstName );
persons.OrderByDescending( p => p.Salary);

等等

【讨论】:

    【解决方案3】:

    要让它在 lambda 中工作,表达式需要形成一个 Comparison&lt;T&gt; 签名。这将需要 2 个“Person”实例。你可以这样做:

    public static void SortPeople(
        this List<Person> 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;
                 });
    }
    

    【讨论】:

    • 扩展方法需要返回类型为void。
    • 确实如此。 “返回结果”是返回排序顺序的 Comparsion。扩展方法只是 { lst.Sort(...); }
    • 不,我只是说 SortPeople 方法的返回类型为 List ,它不会返回,但我猜你只是从他的示例中复制了它......
    • 哦,是的,抱歉 - 很好,已修复。我刚刚从 OP 复制了它,它也有这种设置......
    【解决方案4】:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
         class Program
        {
        static void Main(string[] args)
        {
            List<Person> persons = new List<Person>(); 
            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<Person> 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 }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-29
      • 2010-11-14
      • 2010-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-30
      • 1970-01-01
      相关资源
      最近更新 更多