Nesnedeki bir özellik tarafından bir liste nasıl sıralanır

gibi özelliklere sahip olan Order adlı bir sınıfım var OrderId , OrderDate , Quantity , ve Total . Bu Order sınıfının bir listesi var:

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

şimdi listeyi Order nesnesinin bir özelliğine göre sıralamak istiyorum, örneğin sipariş tarihine veya sipariş kimliğine göre sıralamam gerekiyor.

bunu C# ' de nasıl yapabilirim?

936
tarihinde sordu poke 2010-07-22 17:13:25
kaynak

19 ответов

düşünebildiğim en kolay yol Linq kullanmaktır:

List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
1376
cevap Lazarus 2015-03-20 23:54:49
kaynak

listeyi yerinde sıralamanız gerekiyorsa, Sort yöntemini, Comparison<T> delege:

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

yerinde sıralamak yerine yeni, sıralanmış bir dizi oluşturmayı tercih ederseniz, LİNQ OrderBy yöntemini diğer cevaplarda belirtildiği gibi kullanabilirsiniz.

527
cevap LukeH 2010-07-22 17:28:33
kaynak

LİNQ olmadan bunu yapmak için .Net2.0:

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

eğer açarsan .Net3.0, sonra Lukeh'in cevabı peşinde olduğunuz şeydir.

birden çok özellik üzerinde sıralamak için, yine de bir temsilci içinde yapabilirsiniz. Örneğin:

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

bu artan tarihleri azalan orderİds verecektir.

Ancak, Ben bu kod yeniden kullanımı olmadan yerlerde bir sürü anlamına gelecektir olarak delegeleri yapışmasını tavsiye etmem. Bir IComparer uygulamak ve sadece Sort yöntemine geçmek gerekir. Bkz. burada .

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

ve daha sonra bu IComparer sınıfını kullanmak için, onu örnekleyin ve sıralama yönteminize geçirin:

IComparer<Order> comparer = new MyOrderingClass();
orderList.Sort(comparer);
202
cevap GenericTypeTea 2017-05-23 14:47:29
kaynak

bir liste sipariş etmenin en basit yolu OrderBy

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

aşağıdaki SQL sorgusu gibi birden çok sütun tarafından sipariş etmek istiyorsanız.

ORDER BY OrderDate, OrderId

bunu başarmak için aşağıdaki gibi ThenBy kullanabilirsiniz.

  List<Order> objListOrder = 
    source.OrderBy(order => order.OrderDate).ThenBy(order => order.OrderId).ToList();
79
cevap PSK 2018-06-13 10:41:39
kaynak

dediğiniz gibi Linq olmadan yapıyor:

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

sonra Ara .sıralama () siparişlerin listenizde

31
cevap Jimmy Hoffa 2014-01-30 20:36:40
kaynak

Klasik Bir Nesne Yönelimli Çözüm

önce LİNQ awesomeness genuflect gerekir.... Şimdi

yolundan çıkardık.

JimmyHoffa cevabında bir varyasyon. Jeneriklerle CompareTo parametresi tip güvenli hale gelir.

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

bu varsayılan sortability elbette yeniden kullanılabilir. Yani her istemci gereksiz sıralama mantığı yeniden yazmak zorunda değildir. Tokuş "1" ve " -1 " (veya mantık operatörleri, seçiminiz) sıralama sırasını tersine çevirir.

21
cevap radarbob 2017-02-11 08:41:48
kaynak

/ / bir gridview

ile kullanım için tamamen genel sıralama
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);
    }
15
cevap roger 2013-06-13 05:37:08
kaynak

işte listenin ekstra bir kopyasını oluşturmayan genel bir LINQ uzantısı yöntemidir:

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

kullanmak için:

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

geçenlerde bir ICompare<U> kabul eden bu ek bir tane inşa ettim , böylece karşılaştırmayı özelleştirebilirsiniz. Doğal bir dize yapmak gerektiğinde bu kullanışlı geldi sıralama:

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)));
}
5
cevap Peter 2014-04-09 01:06:09
kaynak

LİNQ kullanarak

objListOrder = GetOrderList()
                   .OrderBy(o => o.OrderDate)
                   .ToList();

objListOrder = GetOrderList()
                   .OrderBy(o => o.OrderId)
                   .ToList();
3
cevap Daniel A. White 2010-07-22 17:16:27
kaynak
//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;
3
cevap Waqas Ahmed 2011-11-24 01:51:44
kaynak

Roger'ın versiyonunun geliştirilmiş.

GetDynamicSortProperty ile ilgili sorun sadece özellik adlarını almaktır, ancak Gridview'de NavigationProperties kullanırsak ne olur? boş bulduğu beri bir istisna göndereceğiz.

örnek:

"çalışan.Misafir.İsim; " çökecek... bu yana değerini almak için bir parametre olarak sadece "isim" sağlar.

işte sıralamamızı sağlayan geliştirilmiş bir versiyon navigasyon özelliklerine göre.

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


    } 
3
cevap user1013375 2013-07-04 18:32:52
kaynak

özellik seçimi hakkında daha genel bir şey yapabilir, ancak 'sipariş':

işlevinizi genel olarak yazın:

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

ve sonra şu şekilde kullanın:

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

daha genel olabilir ve sipariş etmek istediğiniz şey için açık bir tür tanımlayabilirsiniz:

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

ve aynı şekilde kullanın:

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

LİNQ tarzı'OrderBy' yapmanın aptalca ve karmaşık bir yoludur, Ancak,

genel bir şekilde nasıl uygulanabileceğine dair bir ipucu verebilir
3
cevap Danny Mor 2015-04-02 13:26:08
kaynak

lütfen @LukeH tarafından cevabı bazı örnek kodlarla tamamlamama izin verin, çünkü test ettim, bazıları için yararlı olabileceğine inanıyorum:

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 ...
}
3
cevap molbalga 2016-07-19 13:18:06
kaynak

yukarıdaki cevapların hiçbiri benim için yeterince genel değildi, bu yüzden bunu yaptım:

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

büyük veri kümelerine dikkat edin. Bu kolay kod ama koleksiyon büyük ve koleksiyonun nesne türü alanları çok sayıda varsa sorun alabilir. Çalışma süresi nxm nerede:

n = koleksiyondaki öğelerin #

M = # nesne içindeki özellikler

2
cevap itcropper 2016-08-22 21:45:36
kaynak
var obj = db.Items.Where...

var orderBYItemId = obj.OrderByDescending(c => Convert.ToInt32(c.ID));
2
cevap Jevgenij Kononov 2017-05-31 11:26:36
kaynak

LiNQ kullanımı OrderBy

List<Order> objListOrder=new List<Order> ();
    objListOrder=GetOrderList().OrderBy(o=>o.orderid).ToList();
1
cevap Pranay Rana 2010-07-22 17:16:31
kaynak

dayalı GenericTypeTea 'S karşılaştırıcı:

sıralama bayrakları ekleyerek daha fazla esneklik elde edebiliriz:

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

bu senaryoda, myorderingclass açıkça( daha ziyade IComparer olarak örneği gerekir )

sıralama özelliklerini ayarlamak için:

MyOrderingClass comparer = new MyOrderingClass();  
comparer.DateDescending = ...;  
comparer.OrderIdDescending = ...;  
orderList.Sort(comparer);  
1
cevap Jack Griffin 2015-01-06 17:05:49
kaynak
Performans açısından

en iyisi sıralanmış bir liste kullanmaktır, böylece sonuç olarak eklenen veriler sıralanır. Diğer yaklaşımların veriler üzerinde en az bir ekstra yinelemeye ihtiyacı vardır ve çoğu verilerin bir kopyasını oluşturur, böylece yalnızca performans değil, bellek kullanımı da etkilenir. Yüzlerce öğe ile ilgili bir sorun olmayabilir, ancak binlerce, özellikle de birçok eşzamanlı isteğin aynı anda sıralama yapabileceği hizmetlerde olacaktır. Sisteme bir göz atın.Koleksiyon.Genel ad alanı ve liste yerine sıralama ile bir sınıf seçin.

ve mümkünse yansıma kullanarak genel uygulamalardan kaçının, bu da performans sorunlarına neden olabilir.

0
cevap user3285954 2014-07-31 15:53:17
kaynak

nullable türleri ile çalışan Value CompareTo kullanmak için gereklidir .

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

0
cevap Jude 2017-01-19 18:35:41
kaynak

Diğer sorular c# generics sorting list