C# - 使用扩展方法排序

发布于 2024-08-13 02:22:28 字数 689 浏览 6 评论 0原文

lambda 表达式对人员列表进行排序,

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
 }

排序的方法是什么?

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

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

I want to sort a list of person say

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

based on

public enum CompareOptions
 {
    ByFirstName,
    ByLastName,
    BySalary
 }

 public enum SortOrder
 {
   Ascending,
   Descending
 }

using lambda expression what is the way to go for sorting?

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

奢望 2024-08-20 02:22:28

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

第一步是根据 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();
  }
}

默认情况下,该函数将按升序排序。如果您希望它下降,只需否定该值即可。 版本来完成,

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

所以现在编写 SortPeople 可以通过以下EDIT

该版本 100% 在 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;
   });
}

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;
   });
}
自此以后,行同陌路 2024-08-20 02:22:28

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

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

等等。

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.

对你的占有欲 2024-08-20 02:22:28

要使其在 lambda 中工作,表达式需要形成 比较签名。这将需要 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;
             });
}

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;
             });
}
無處可尋 2024-08-20 02:22:28
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 }

}

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 }

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文