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