c# - sort排序 - list sort java




如何按对象中的属性对List<T>进行排序 (13)

我有一个名为Order的类,它具有OrderIdOrderDateQuantityTotal等属性。 我有这个Order类的列表:

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

现在我想根据Order对象的一个​​属性对列表进行排序,例如我需要按订单日期或订单ID对其进行排序。

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


//完全通用的排序与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);
    }

面向对象的经典解决方案

首先,我必须对LINQ的迷人魅力进行归纳....现在我们已经取得了进展

JimmyHoffa答案的变化。 使用泛型时, 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”(或逻辑运算符,您的选择)会颠倒排序顺序。


从性能角度来看,最好的方法是使用排序列表,以便数据在添加结果时进行排序。 其他方法至少需要对数据进行一次额外迭代,大多数方法会创建数据副本,这样不仅性能,而且内存使用率也会受到影响。 可能不是几百个元素的问题,但会有数千个问题,特别是在许多并发请求可能同时进行排序的服务中。 查看System.Collections.Generic命名空间并选择一个具有排序而不是List的类。

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


任何使用可空类型的人都必须使用Value来使用CompareTo

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


利用LiNQ OrderBy

List<Order> objListOrder=new List<Order> ();
    objListOrder=GetOrderList().OrderBy(o=>o.orderid).ToList();

在.Net2.0上不使用LINQ就可以做到这一点:

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

这会给你升序日期降序 orderIds。

但是,我不会推荐坚持代表,因为这将意味着很多地方没有代码重用。 您应该实现一个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类,实例化它并将它传递给你的Sort方法:

IComparer<Order> comparer = new MyOrderingClass();
orderList.Sort(comparer);

如果你想要类似的东西

ORDER BY OrderDate, OrderId

然后尝试如下。

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

如果您需要就地对列表进行排序,那么您可以使用Sort方法,传递一个Comparison<T>委托:

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

如果您更喜欢创建一个新的排序序列,而不是就地排序,那么您可以使用LINQ的OrderBy方法,如其他答案中所述。


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

List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();

正如你所说的那样,不用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()


请让我用@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 ...
}

这是一个通用的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)));
}

var obj = db.Items.Where...

var orderBYItemId = obj.OrderByDescending(c => Convert.ToInt32(c.ID));




sorting