2009-12-01 42 views
9

Tôi muốn sắp xếp một danh sách các người nóiC# - Sắp xếp sử dụng Extension Method

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

dựa trên

public enum CompareOptions 
{ 
    ByFirstName, 
    ByLastName, 
    BySalary 
} 

public enum SortOrder 
{ 
    Ascending, 
    Descending 
} 

sử dụng biểu thức lambda con đường để đi để phân loại là gì?

public static List<Person> SortPeople(this List<Person> lst, 
    CompareOptions opt1,SortOrder ord) 

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

Tốt câu hỏi. Bạn đang làm cho các chuyên gia sản xuất mã nhỏ gọn và dễ đọc. Tất cả chúng ta đều học hỏi từ điều này. Cảm ơn!! – shahkalpesh

+0

Cảm ơn tất cả vì đã giúp đỡ – user215675

+0

@Shahkalpesh, Bạn cũng đã giúp tôi rất nhiều cho những câu hỏi cũ của tôi. Tôi muốn nhân cơ hội này để cảm ơn bạn một lần nữa. – user215675

Trả lời

8

Dường như bạn đang cố gắng để gọi Xếp theo phương pháp trên List<T> mà phải mất một đại biểu Comparison<T>. Điều này sẽ đòi hỏi một chút công việc vì trước tiên bạn phải xác định một hàm so sánh tương thích.

Bước đầu tiên là viết một hàm so sánh dựa trên giá trị 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(); 
    } 
} 

Theo mặc định chức năng này sẽ sắp xếp theo thứ tự tăng dần. Nếu bạn muốn nó được giảm dần chỉ đơn giản là phủ nhận giá trị. Vì vậy, bây giờ đang viết SortPeople có thể được thực hiện bằng cách sau đây

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 đó được thực hiện 100% trong một 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

Điều này là tốt đẹp và sạch sẽ, nhưng nó không thực sự hiển thị như thế nào để làm điều đó trong một lambda, đó là những gì OP yêu cầu. –

+0

@Reed Copsey Tôi sẽ không khuyên bạn nên làm nó chỉ trong một lamba, như mọi so sánh sẽ ngang qua tất cả các ifs, không chỉ một lần để chọn lambda chính xác để sử dụng. – Wilhelm

+0

@Reed, đúng, tôi đã cập nhật câu trả lời để bao gồm một phiên bản lambda thuần túy. – JaredPar

3

Để có được điều này để làm việc trong một lambda, các biểu thức cần phải tạo thành chữ ký Comparison<T>. Điều này sẽ mất 2 trường hợp "Person". Bạn có thể làm như thế này:

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

Phương pháp mở rộng cần có khoảng trống trả về. –

+0

."Kết quả trả về" là Comparsion trả lại thứ tự sắp xếp. Phương thức mở rộng chỉ là {lst.Sort (...); } –

+0

Không, tôi chỉ nói rằng phương thức SortPeople có kiểu trả về của Danh sách mà nó không trả lại, nhưng tôi đoán bạn chỉ sao chép từ ví dụ của mình ... –

2
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 } 

}

6

Bạn có thực sự cần sự đếm? Tôi không nghĩ rằng đóng gói Logic tìm kiếm của bạn trong một phương pháp rõ ràng hơn nhiều hoặc nhiều DRY hơn là chỉ sử dụng phương pháp LINQ:

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

, vv

Các vấn đề liên quan