How to Sort a List by a property in the object

前端 未结 20 1974
醉梦人生
醉梦人生 2020-11-21 08:25

I have a class called Order which has properties such as OrderId, OrderDate, Quantity, and Total. I have a l

相关标签:
20条回答
  • 2020-11-21 08:43

    To do this without LINQ on .Net2.0:

    List<Order> objListOrder = GetOrderList();
    objListOrder.Sort(
        delegate(Order p1, Order p2)
        {
            return p1.OrderDate.CompareTo(p2.OrderDate);
        }
    );
    

    If you're on .Net3.0, then LukeH's answer is what you're after.

    To sort on multiple properties, you can still do it within a delegate. For example:

    orderList.Sort(
        delegate(Order p1, Order p2)
        {
            int compareDate = p1.Date.CompareTo(p2.Date);
            if (compareDate == 0)
            {
                return p2.OrderID.CompareTo(p1.OrderID);
            }
            return compareDate;
        }
    );
    

    This would give you ascending dates with descending orderIds.

    However, I wouldn't recommend sticking delegates as it will mean lots of places without code re-use. You should implement an IComparer and just pass that through to your Sort method. See here.

    public class MyOrderingClass : IComparer<Order>
    {
        public int Compare(Order x, Order y)
        {
            int compareDate = x.Date.CompareTo(y.Date);
            if (compareDate == 0)
            {
                return x.OrderID.CompareTo(y.OrderID);
            }
            return compareDate;
        }
    }
    

    And then to use this IComparer class, just instantiate it and pass it to your Sort method:

    IComparer<Order> comparer = new MyOrderingClass();
    orderList.Sort(comparer);
    
    0 讨论(0)
  • 2020-11-21 08:47

    Here is a generic LINQ extension method that does not create an extra copy of the list:

    public static void Sort<T,U>(this List<T> list, Func<T, U> expression)
        where U : IComparable<U>
    {
        list.Sort((x, y) => expression.Invoke(x).CompareTo(expression.Invoke(y)));
    }
    

    To use it:

    myList.Sort(x=> x.myProperty);
    

    I recently built this additional one which accepts an ICompare<U>, so that you can customize the comparison. This came in handy when I needed to do a Natural string sort:

    public static void Sort<T, U>(this List<T> list, Func<T, U> expression, IComparer<U> comparer)
        where U : IComparable<U>
    {    
        list.Sort((x, y) => comparer.Compare(expression.Invoke(x), expression.Invoke(y)));
    }
    
    0 讨论(0)
  • 2020-11-21 08:47

    Anybody working with nullable types, Value is required to use CompareTo.

    objListOrder.Sort((x, y) => x.YourNullableType.Value.CompareTo(y.YourNullableType.Value));

    0 讨论(0)
  • 2020-11-21 08:50

    Doing it without Linq as you said:

    public class Order : IComparable
    {
        public DateTime OrderDate { get; set; }
        public int OrderId { get; set; }
    
        public int CompareTo(object obj)
        {
            Order orderToCompare = obj as Order;
            if (orderToCompare.OrderDate < OrderDate || orderToCompare.OrderId < OrderId)
            {
                return 1;
            }
            if (orderToCompare.OrderDate > OrderDate || orderToCompare.OrderId > OrderId)
            {
                return -1;
            }
    
            // The orders are equivalent.
            return 0;
        }
    }
    

    Then just call .sort() on your list of Orders

    0 讨论(0)
  • 2020-11-21 08:50

    You can do something more generic about the properties selection yet be specific about the type you're selecting from, in your case 'Order':

    write your function as a generic one:

    public List<Order> GetOrderList<T>(IEnumerable<Order> orders, Func<Order, T> propertySelector)
            {
                return (from order in orders
                        orderby propertySelector(order)
                        select order).ToList();
            } 
    

    and then use it like this:

    var ordersOrderedByDate = GetOrderList(orders, x => x.OrderDate);
    

    You can be even more generic and define an open type for what you want to order:

    public List<T> OrderBy<T,P>(IEnumerable<T> collection, Func<T,P> propertySelector)
            {
                return (from item in collection
                        orderby propertySelector(item)
                        select item).ToList();
            } 
    

    and use it the same way:

    var ordersOrderedByDate = OrderBy(orders, x => x.OrderDate);
    

    Which is a stupid unnecessary complex way of doing a LINQ style 'OrderBy', But it may give you a clue of how it can be implemented in a generic way

    0 讨论(0)
  • 2020-11-21 08:50

    Suppose you have the following code, in this code, we have a Passenger class with a couple of properties that we want to sort based on.

    public class Passenger
    {
        public string Name { get; }
        public string LastName { get; }
        public string PassportNo { get; }
        public string Nationality { get; }
    
        public Passenger(string name, string lastName, string passportNo, string nationality)
        {
            this.Name = name;
            this.LastName = lastName;
            this.PassportNo = passportNo;
            this.Nationality = nationality;
        }
    
        public static int CompareByName(Passenger passenger1, Passenger passenger2)
        {
            return String.Compare(passenger1.Name, passenger2.Name);
        }
    
        public static int CompareByLastName(Passenger passenger1, Passenger passenger2)
        {
            return String.Compare(passenger1.LastName, passenger2.LastName);
        }
    
        public static int CompareNationality(Passenger passenger1, Passenger passenger2)
        {
            return String.Compare(passenger1.Nationality, passenger2.Nationality);
        }
    }
    
    public class TestPassengerSort
    {
        Passenger p1 = new Passenger("Johon", "Floid", "A123456789", "USA");
        Passenger p2 = new Passenger("Jo", "Sina", "A987463215", "UAE");
        Passenger p3 = new Passenger("Ped", "Zoola", "A987855215", "Italy");
    
        public void SortThem()
        {
            Passenger[] passengers = new Passenger[] { p1, p2, p3 };
            List<Passenger> passengerList = new List<Passenger> { p1, p2, p3 };
    
            Array.Sort(passengers, Passenger.CompareByName);
            Array.Sort(passengers, Passenger.CompareByLastName);
            Array.Sort(passengers, Passenger.CompareNationality);
    
            passengerList.Sort(Passenger.CompareByName);
            passengerList.Sort(Passenger.CompareByLastName);
            passengerList.Sort(Passenger.CompareNationality);
    
        }
    }
    

    So you can implement your sort structure by using Composition delegate.

    0 讨论(0)
提交回复
热议问题