Pertanyaan Cara Menyortir Daftar oleh properti di objek


Saya memiliki kelas yang disebut Order yang memiliki properti seperti OrderId, OrderDate, Quantity, dan Total. Saya punya daftar ini Order kelas:

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

Sekarang saya ingin mengurutkan daftar berdasarkan satu properti Order objek, misalnya saya harus mengurutkan berdasarkan tanggal pesanan atau ID pesanan.

Bagaimana saya bisa melakukan ini di C #?


902
2017-07-22 13:13


asal


Jawaban:


Cara termudah yang dapat saya pikirkan adalah menggunakan Linq:

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

1328
2017-07-22 13:16



Jika Anda perlu mengurutkan daftar di tempat maka Anda dapat menggunakan Sort metode, melewati a Comparison<T> melimpahkan:

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

Jika Anda lebih suka membuat urutan baru yang disortir daripada mengurutkan di tempat maka Anda dapat menggunakan LINQ OrderBy metode, seperti yang disebutkan dalam jawaban lainnya.


501
2017-07-22 13:23



Untuk melakukan ini tanpa LINQ di .Net2.0:

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

Jika Anda menggunakan .Net3.0, maka LukeH menjawab adalah apa yang Anda harapkan.

Untuk mengurutkan beberapa properti, Anda masih dapat melakukannya di dalam delegasi. Sebagai contoh:

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

Ini akan memberi Anda naik tanggal dengan turun orderIds.

Namun, saya tidak akan merekomendasikan pelepasan delegasi karena ini akan berarti banyak tempat tanpa penggunaan ulang kode. Anda harus menerapkan IComparer dan hanya menyampaikannya ke Anda Sort metode. Lihat sini.

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

Dan kemudian untuk menggunakan kelas IComparer ini, cukup instantiate dan lewati ke metode Sortir Anda:

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

197
2017-07-22 13:35



Cara paling sederhana untuk memesan daftar adalah dengan menggunakan OrderBy

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

Jika Anda ingin memesan dengan beberapa kolom seperti berikut SQL Query.

ORDER BY OrderDate, OrderId

Untuk mencapai ini, Anda dapat menggunakan ThenBy seperti berikut.

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

76
2017-07-22 13:23



Melakukannya tanpa Linq seperti yang Anda katakan:

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

Kemudian cukup panggil .sort () pada daftar Pesanan Anda


31
2017-07-22 13:55



Solusi Berorientasi Objek Klasik

Pertama saya harus berlutut ke kedahsyatan LINQ .... Sekarang kita sudah mendapatkan itu keluar dari jalan

Variasi jawaban JimmyHoffa. Dengan obat generik CompareTo parameter menjadi tipe aman.

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

Pengurutan default ini dapat digunakan kembali tentu saja. Itu adalah setiap klien tidak harus menulis ulang logika pengurutan secara berlebihan. Menukar "1" dan "-1" (atau operator logika, pilihan Anda) membalik urutan pengurutan.


19
2017-10-16 14:03



// Benar-benar generik menyortir untuk digunakan dengan tampilan grid

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
2018-06-13 01:37



Berikut adalah metode ekstensi LINQ generik yang tidak membuat salinan tambahan dari daftar:

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

Untuk menggunakannya:

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

Saya baru-baru ini membangun satu tambahan yang menerima ICompare<U>, sehingga Anda dapat menyesuaikan perbandingan. Ini berguna ketika saya perlu melakukan semacam string Natural:

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
2018-02-14 14:25



Menggunakan LINQ

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

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

3
2017-07-22 13:16



//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
2017-11-23 21:42



Peningkatan versi Roger.

Masalah dengan GetDynamicSortProperty adalah bahwa hanya mendapatkan nama properti tetapi apa yang terjadi jika di GridView kita menggunakan NavigationProperties? itu akan mengirim pengecualian, karena ia menemukan nol.

Contoh:

"Employee.Company.Name;" akan macet ... karena hanya mengizinkan "Nama" sebagai parameter untuk mendapatkan nilainya.

Berikut ini versi perbaikan yang memungkinkan kita mengurutkan berdasarkan Properti Navigasi.

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
2017-07-04 14:32