代码之家  ›  专栏  ›  技术社区  ›  Shyju

如何按对象中的属性对列表排序

  •  1024
  • Shyju  · 技术社区  · 14 年前

    我有一门课叫 Order 具有以下特性 OrderId , OrderDate , Quantity ,和 Total 订单 班级:

    List<Order> objListOrder = new List<Order>();
    GetOrderList(objListOrder); // fill list of orders
    

    订单 对象,例如,我需要按订单日期或订单id对其排序。

    如何在C#中执行此操作?

    19 回复  |  直到 9 年前
        1
  •  1974
  •   Kyle Alons    9 年前

    我能想到的最简单的方法是使用Linq:

    List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
    
        2
  •  904
  •   Kolappan N t-clausen.dk    6 年前

    如果需要对列表进行排序,那么可以使用 Sort 方法,传递 Comparison<T>

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

    OrderBy 方法,如其他答案所述。

        3
  •  230
  •   Community pid    7 年前

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

    如果你在.Net3.0上,那么LukeH answer

    要对多个属性进行排序,仍然可以在委托中进行排序。例如:

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

    日期 降序

    IComparer 把它传给你的朋友 Sort 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;
        }
    }
    

    IComparer<Order> comparer = new MyOrderingClass();
    orderList.Sort(comparer);
    
        4
  •  121
  •   PSK    6 年前

    排序列表的最简单方法是使用 OrderBy

     List<Order> objListOrder = 
        source.OrderBy(order => order.OrderDate).ToList();
    

    如果您想按多个列排序,如下面的SQL查询。

    ORDER BY OrderDate, OrderId
    

    要实现这一点,您可以使用 ThenBy 喜欢跟在后面。

      List<Order> objListOrder = 
        source.OrderBy(order => order.OrderDate).ThenBy(order => order.OrderId).ToList();
    
        5
  •  34
  •   Jimmy Hoffa    11 年前

    没有Linq的情况下,就像你说的:

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

    然后只需在订单列表中调用.sort()

        6
  •  28
  •   radarbob    8 年前

    经典的面向对象解决方案

    CompareTo 参数变为类型安全。

    public class Order : IComparable<Order> {
    
        public int CompareTo( Order that ) {
            if ( that == null ) return 1;
            if ( this.OrderDate > that.OrderDate) return 1;
            if ( this.OrderDate < that.OrderDate) return -1;
            return 0;
        }
    }
    
    // in the client code
    // assume myOrders is a populated List<Order>
    myOrders.Sort(); 
    

    这个默认的可排序性当然是可重用的。也就是说,每个客户机不必冗余地重新编写排序逻辑。交换“1”和“-1”(或逻辑运算符,由您选择)将反转排序顺序。

        7
  •  18
  •   roger    11 年前

    //用于gridview的完全通用排序

    public List<T> Sort_List<T>(string sortDirection, string sortExpression, List<T> data)
        {
    
            List<T> data_sorted = new List<T>();
    
            if (sortDirection == "Ascending")
            {
                data_sorted = (from n in data
                                  orderby GetDynamicSortProperty(n, sortExpression) ascending
                                  select n).ToList();
            }
            else if (sortDirection == "Descending")
            {
                data_sorted = (from n in data
                                  orderby GetDynamicSortProperty(n, sortExpression) descending
                                  select n).ToList();
    
            }
    
            return data_sorted;
    
        }
    
        public object GetDynamicSortProperty(object item, string propName)
        {
            //Use reflection to get order type
            return item.GetType().GetProperty(propName).GetValue(item, null);
        }
    
        8
  •  7
  •   Peter    10 年前

    下面是一个通用的LINQ扩展方法,它不会创建列表的额外副本:

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

    要使用它:

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

    我最近建立了这个额外的一个接受 ICompare<U> ,以便自定义比较。当我需要做一个自然的字符串排序时,这就派上了用场:

    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)));
    }
    
        9
  •  5
  •   Daniel A. White    14 年前

    objListOrder = GetOrderList()
                       .OrderBy(o => o.OrderDate)
                       .ToList();
    
    objListOrder = GetOrderList()
                       .OrderBy(o => o.OrderId)
                       .ToList();
    
        10
  •  4
  •   Waqas Ahmed    13 年前
    //Get data from database, then sort list by staff name:
    
    List<StaffMember> staffList = staffHandler.GetStaffMembers();
    
    var sortedList = from staffmember in staffList
                     orderby staffmember.Name ascending
                     select staffmember;
    
        11
  •  4
  •   molbalga    8 年前

    请让我通过@LukeH和一些示例代码来完成答案,因为我已经测试了它,我相信它可能对某些人有用:

    public class Order
    {
        public string OrderId { get; set; }
        public DateTime OrderDate { get; set; }
        public int Quantity { get; set; }
        public int Total { get; set; }
    
        public Order(string orderId, DateTime orderDate, int quantity, int total)
        {
            OrderId = orderId;
            OrderDate = orderDate;
            Quantity = quantity;
            Total = total;
        }
    }
    
    public void SampleDataAndTest()
    {
        List<Order> objListOrder = new List<Order>();
    
        objListOrder.Add(new Order("tu me paulo ", Convert.ToDateTime("01/06/2016"), 1, 44));
        objListOrder.Add(new Order("ante laudabas", Convert.ToDateTime("02/05/2016"), 2, 55));
        objListOrder.Add(new Order("ad ordinem ", Convert.ToDateTime("03/04/2016"), 5, 66));
        objListOrder.Add(new Order("collocationem ", Convert.ToDateTime("04/03/2016"), 9, 77));
        objListOrder.Add(new Order("que rerum ac ", Convert.ToDateTime("05/02/2016"), 10, 65));
        objListOrder.Add(new Order("locorum ; cuius", Convert.ToDateTime("06/01/2016"), 1, 343));
    
    
        Console.WriteLine("Sort the list by date ascending:");
        objListOrder.Sort((x, y) => x.OrderDate.CompareTo(y.OrderDate));
    
        foreach (Order o in objListOrder)
            Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);
    
        Console.WriteLine("Sort the list by date descending:");
        objListOrder.Sort((x, y) => y.OrderDate.CompareTo(x.OrderDate));
        foreach (Order o in objListOrder)
            Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);
    
        Console.WriteLine("Sort the list by OrderId ascending:");
        objListOrder.Sort((x, y) => x.OrderId.CompareTo(y.OrderId));
        foreach (Order o in objListOrder)
            Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);
    
        //etc ...
    }
    
        12
  •  3
  •   Miguel Becerra    11 年前

    罗杰版本的改进版。

    例子:

    “Employee.Company.Name;”会崩溃。。。因为只允许“Name”作为参数来获取其值。

    这是一个改进的版本,允许我们按导航属性排序。

    public object GetDynamicSortProperty(object item, string propName)
        {
            try
            {                 
                string[] prop = propName.Split('.'); 
    
                //Use reflection to get order type                   
                int i = 0;                    
                while (i < prop.Count())
                {
                    item = item.GetType().GetProperty(prop[i]).GetValue(item, null);
                    i++;
                }                     
    
                return item;
            }
            catch (Exception ex)
            {
                throw ex;
            }
    
    
        } 
    
        13
  •  3
  •   Danny Mor    9 年前

    将函数编写为泛型函数:

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

    然后像这样使用:

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

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

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

    这是一种愚蠢的、不必要的、复杂的方式来执行LINQ样式的“OrderBy”, 但它可能会给你一个线索,告诉你如何以一种通用的方式实现它

        14
  •  3
  •   Jevgenij Kononov    7 年前
    var obj = db.Items.Where...
    
    var orderBYItemId = obj.OrderByDescending(c => Convert.ToInt32(c.ID));
    
        15
  •  1
  •   Pranay Rana    14 年前

    利用LiNQ OrderBy

    List<Order> objListOrder=new List<Order> ();
        objListOrder=GetOrderList().OrderBy(o=>o.orderid).ToList();
    
        16
  •  1
  •   Jack Griffin    10 年前

    基于 的比较器:
    我们可以通过添加排序标志来获得更大的灵活性:

    public class MyOrderingClass : IComparer<Order> {  
        public int Compare(Order x, Order y) {  
            int compareDate = x.Date.CompareTo(y.Date);  
            if (compareDate == 0) {  
                int compareOrderId = x.OrderID.CompareTo(y.OrderID);  
    
                if (OrderIdDescending) {  
                    compareOrderId = -compareOrderId;  
                }  
                return compareOrderId;  
            }  
    
            if (DateDescending) {  
                compareDate = -compareDate;  
            }  
            return compareDate;  
        }  
    
        public bool DateDescending { get; set; }  
        public bool OrderIdDescending { get; set; }  
    }  
    

    MyOrderingClass类 明确地(而不是 )
    要设置其排序属性:

    MyOrderingClass comparer = new MyOrderingClass();  
    comparer.DateDescending = ...;  
    comparer.OrderIdDescending = ...;  
    orderList.Sort(comparer);  
    
        17
  •  1
  •   itcropper    8 年前

    以上答案对我来说都不够笼统,所以我做了这个:

    var someUserInputStringValue = "propertyNameOfObject i.e. 'Quantity' or 'Date'";
    var SortedData = DataToBeSorted
                       .OrderBy(m => m.GetType()
                                      .GetProperties()
                                      .First(n => 
                                          n.Name == someUserInputStringValue)
                       .GetValue(m, null))
                     .ToList();
    

    不过,在海量数据集上要小心。这是一个简单的代码,但如果集合很大,并且集合的对象类型有大量字段,则可能会给您带来麻烦。 运行时间为NxM,其中:

    N=集合中元素的#

    M=对象中属性的#

        18
  •  1
  •   Jude    8 年前

    任何使用可空类型的人, Value CompareTo .

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

        19
  •  1
  •   Seyedraouf Modarresi    4 年前

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

    因此,您可以通过使用组合委托来实现排序结构。

        20
  •  0
  •   user3285954    10 年前

    从性能的角度来看,最好的方法是使用排序列表,以便在将数据添加到结果时对其进行排序。 查看System.Collections.Generic命名空间,然后选择一个具有排序而不是列表的类。

    尽可能避免使用反射的泛型实现,这也会导致性能问题。

        21
  •  0
  •   luka    4 年前

    如果您想排序这个序列的列表“1”“10”“100”“200”“2”“20”“3”“30”“300”,并得到这个表单中的排序项1;2;三;10;20;30;100;200;300您可以使用:

     public class OrderingAscending : IComparer<String>
        {
            public int Compare(String x, String y)
            {
                Int32.TryParse(x, out var xtmp);
                Int32.TryParse(y, out var ytmp);
    
                int comparedItem = xtmp.CompareTo(ytmp);
                return comparedItem;
            }
        }
    

    您可以在以下表单的代码隐藏中使用它:

     IComparer<String> comparerHandle = new OrderingAscending();
     yourList.Sort(comparerHandle);
    
        22
  •  0
  •   Dev-lop-er    3 年前
    • 在解析Id之后,使用Sort函数和委托对Id进行排序 价值

        class Question
        {
            public List<QuestionInfo> Questions Info{ get; set; }
        
        }
    
        class QuestionInfo
        {
            public string Id{ get; set; }
            public string Questions{ get; set; }
        
        }
    
        var questionnaire = new Question();
    
        questionnaire.QuestionInfo.Sort(delegate(Entities.Question x, Entities.Question y)
                            {
                                return int.Parse(x.Id) - int.Parse(y.Id);
                            });