C# - Sorting using Extension Method

前端 未结 4 981
野趣味
野趣味 2021-02-08 06:41

I want to sort a list of person say

List persons=new List();
persons.Add(new Person(\"Jon\",\"Bernald\",45000.89));
persons.Add(new P         


        
相关标签:
4条回答
  • 2021-02-08 07:25
    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 }
    

    }

    0 讨论(0)
  • 2021-02-08 07:34

    To get this to work in a lambda, the expression needs to form a Comparison<T> signature. This would take 2 "Person" instances. You could do this like:

    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;
                 });
    }
    
    0 讨论(0)
  • 2021-02-08 07:42

    Do you really need the enums? I don't think that encapsulating your search logic in a method is much clearer or more DRY than just using linq methods:

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

    etc.

    0 讨论(0)
  • 2021-02-08 07:46

    It looks like you are attempting to call the Sort method on List<T> which takes a Comparison<T> delegate. This will require a bit of work because you first have to define a compatible comparison function.

    First step is to write a comparison function based on the CompareOptions value

    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();
      }
    }
    

    By default this function will sort in ascending order. If you want it to be descending simply negate the value. So now writing SortPeople can be done by the following

    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);
    }
    

    EDIT

    Version which is done 100% in a lambda

    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;
       });
    }
    
    0 讨论(0)
提交回复
热议问题