วิธีการเรียงลำดับรายการ <T> ตามคุณสมบัติในวัตถุ


1248

ฉันได้เรียนที่เรียกว่าOrderซึ่งมีคุณสมบัติเช่นOrderId, OrderDate, และQuantity Totalฉันมีรายชื่อของOrderชั้นนี้:

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

ตอนนี้ฉันต้องการเรียงลำดับรายการตามคุณสมบัติหนึ่งของOrderวัตถุเช่นฉันต้องการเรียงลำดับตามวันที่สั่งซื้อหรือรหัสสั่งซื้อ

ฉันจะทำสิ่งนี้ใน C # ได้อย่างไร


9
รอ - คุณต้องการเรียงลำดับตามวันที่สั่งซื้อและรหัสการสั่งซื้อหรือไม่ เพราะคำตอบส่วนใหญ่ดูเหมือนจะคิดว่าคุณเรียงลำดับอย่างใดอย่างหนึ่งเท่านั้น
GalacticCowboy

@GalacticCowboy, @GenericTypeTea: คำถามที่ถามว่า "ฉันต้องการเรียงลำดับรายการตามคุณสมบัติหนึ่งเดียวของออบเจกต์ Order" แต่ฉันเห็นด้วยที่อื่นไม่ชัดเจน ไม่ว่าจะด้วยวิธีใดก็ไม่ได้สร้างความแตกต่างอย่างมากไม่ว่าคุณจะต้องเรียงลำดับตามคุณสมบัติเดียวหรือหลายแห่ง
ลุ

@LukeH - เพิ่งอ่านใหม่อีกครั้งและฉันเห็นด้วย 'ฉันต้องการเรียงลำดับรายการตามคุณสมบัติหนึ่งรายการ' ... และ 'วันที่สั่งซื้อหรือรหัสสั่งซื้อ' ระหว่างคำตอบทั้งหมดเรามีฐานครอบคลุมทั้งหมด :)
djdd87

คำตอบ:


1807

วิธีที่ง่ายที่สุดที่ฉันคิดได้คือใช้ Linq:

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

22
ฉันจะเรียงลำดับสิ่งนี้จากมากไปน้อยได้อย่างไร
หมีน่ารัก

229
@BonusKun List <Order> SortedList = objListOrder OrderByDescending (o => o.OrderDate) .ToList ();
javajavajavajavajava

77
โปรดทราบว่าสิ่งนี้จะสร้างรายการใหม่ทั้งหมดพร้อมรายการทั้งหมดในหน่วยความจำซึ่งอาจมีปัญหาในด้านประสิทธิภาพ
staafl

14
@staafl จะlistWithObjects = listWithObjects.OrderByDescending(o => o.Status).ToList();พอเพียงสำหรับความพยายามหรือไม่
Andrew Grinder

28
@staafl เรากำลังสั่งรายการของการอ้างอิงวัตถุไม่ใช่การทำซ้ำวัตถุเองเท่าที่ฉันรู้ แม้ว่าหน่วยความจำนี้จะเพิ่มเป็นสองเท่าของหน่วยความจำที่ใช้โดยรายการอ้างอิง แต่ก็ไม่ได้แย่เหมือนการทำซ้ำวัตถุทั้งหมดดังนั้นในสถานการณ์ส่วนใหญ่ที่อยู่นอกสถานที่ที่เราจัดการกับชุดข้อมูลขนาดใหญ่และเก็บไว้ในหน่วยความจำ มันควรจะพอเพียง
Lazarus

798

หากคุณต้องการเรียงลำดับรายการในสถานที่คุณสามารถใช้Sortวิธีการผ่านComparison<T>ผู้รับมอบสิทธิ์:

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

หากคุณต้องการสร้างลำดับใหม่เรียงลำดับมากกว่าเรียงลำดับในสถานที่คุณสามารถใช้OrderByวิธีการของ LINQ ดังที่กล่าวไว้ในคำตอบอื่น ๆ


30
ใช่นี่คือคำตอบที่ "ถูกต้อง" และควรมีประสิทธิภาพมากกว่าการสร้าง IEnumerable ใหม่แล้วแปลงเป็นรายการใหม่
โจนาธานวู้ด

45
แน่นอนถ้าคุณจำเป็นต้องลงมาเรียงสลับxและอยู่ทางด้านขวามือของลูกศรy =>
Jeppe Stig Nielsen

15
คำตอบที่แท้จริงที่เรียงลำดับรายการตามจริง
Mitchell Currie

3
@PimBrouwers นี่คือช่วงเวลาตัวเลือกที่ดีกว่า แม้ว่าจำนวนหน่วยความจำที่คุณใช้ไม่มีปัญหาวิธีนี้จะช่วยหลีกเลี่ยงการจัดสรรหน่วยความจำที่ไม่จำเป็นซึ่งมีราคาแพงมาก ตัวเลือกนี้เหมือนกับ codewise ที่เรียบง่ายและลำดับของขนาดเร็วขึ้น
Cdaragorn

12
@JonSchneider สำหรับNullable<>(ใช้DateTime?เป็นตัวอย่าง) คุณสามารถใช้.Sort((x, y) => Nullable.Compare(x.OrderDate, y.OrderDate))ซึ่งจะถือว่าเป็นโมฆะเป็นก่อนหน้าค่าที่ไม่ใช่โมฆะทั้งหมด .Sort((x, y) => Comparer<DateTime?>.Default.Compare(x.OrderDate, y.OrderDate)มันเป็นเหมือนกับ
Jeppe Stig Nielsen

219

หากต้องการทำสิ่งนี้โดยไม่ใช้ LINQ บน. Net2.0:

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

หากคุณใช้. Net3.0 คำตอบของลุคคือสิ่งที่คุณต้องการ

ในการจัดเรียงคุณสมบัติหลายรายการคุณยังสามารถทำได้ภายในผู้รับมอบสิทธิ์ ตัวอย่างเช่น:

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วิธีการของคุณ ดูที่นี่

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

1
คำตอบที่ดีเลิศและควรเป็นคำตอบที่ถูกต้องเพราะช่วยป้องกันการเริ่มต้นรายการเดิมใหม่ (ซึ่ง LINQ เวอร์ชั่นจะทำอยู่เสมอ) ให้การห่อหุ้มที่ดีขึ้น
Jeb

@Wonton ไม่ ความคิดคือการมีIComparerการใช้งานที่แตกต่างกันทำให้เรามีพฤติกรรมหลากหลาย
Radarbob

ทำงานให้ฉัน ฉันโพสต์เวอร์ชันนี้พร้อมตัวเลือกการเรียงลำดับ
แจ็คกริฟฟิ

109

วิธีที่ง่ายที่สุดในการสั่งซื้อรายการคือการใช้ OrderBy

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

หากคุณต้องการสั่งซื้อหลายคอลัมน์เช่นติดตาม SQL Query

ORDER BY OrderDate, OrderId

เพื่อให้บรรลุนี้คุณสามารถใช้ThenByดังต่อไปนี้

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

32

ทำโดยไม่ต้อง 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 () ในรายการคำสั่งซื้อของคุณ


3
ก่อนอื่นต้องทำการทดสอบnullกับasนักแสดง ซึ่งเป็นจุดรวมของasเป็น (ฮ่า, ฮ่า) (Order)objโยนข้อยกเว้นเมื่อมันล้มเหลว if(orderToCompare == null) return 1;.
Radarbob

+1 สำหรับการใช้อินเทอร์เฟซซึ่งทำให้รหัสง่ายต่อการบำรุงรักษาและเปิดเผยความสามารถของวัตถุอย่างชัดเจน
AeonOfTime

หาก Bill and Ted เคยปรากฏตัวฉันจะขอให้พวกเขาพาฉันกลับไปที่ 16 ต.ค. 2014 เพื่อให้ฉันสามารถแก้ไขข้อผิดพลาดด้านบน - asส่งคืนnullหากนักแสดงล้มเหลว แต่อย่างน้อยการทดสอบโมฆะก็ถูกต้อง
Radarbob

@radarbob ใช่แล้ว .. โอ๊ะโอ :) แต่! ฟังก์ชั่นนี้ตั้งใจที่จะใช้โดยอัตโนมัติโดยเรียงลำดับรายการที่List<Order>ควรมีการรับประกันประเภทเพื่อให้ตรงกับในasปี 2014 คุณอาจไม่ได้เขียนข้อผิดพลาดมากเท่าที่หลีกเลี่ยงคำสั่งยามที่ไม่จำเป็น :)
Jimmy Hoffa

ควรจะรับประกัน จุดที่น่าสนใจ ถ้ามันถูกห่อหุ้มอย่างดีซึ่งมันไม่สามารถเรียกได้ยกเว้นว่าจะผ่าน a List<Order>; แต่คุณและฉันทั้งคู่ได้พบโปรแกรมเมอร์ที่ห่อหุ้มตัวเองซึ่งไม่ได้พูดสมมุติฐานคือ "ฉันกำลังเขียนรหัสนี้ดังนั้นมันจะไม่ถูกใช้ผิด"
Radarbob

26

วิธีการแก้ปัญหาเชิงวัตถุคลาสสิก

ก่อนอื่นฉันต้องเห็นด้วยกับสุดยอดของ LINQ .... ตอนนี้เรามีทางออกแล้ว

รูปแบบของคำตอบ JimmyHoffa ด้วย generics 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" (หรือตัวดำเนินการตรรกะตัวเลือกของคุณ) จะกลับคำสั่งการจัดเรียง


วิธีการที่ง่ายสำหรับการเรียงลำดับวัตถุในรายการ แต่ฉันไม่เข้าใจว่าทำไมคุณกลับ 1 ถ้า (นั่น == เป็นโมฆะ)?
Loc Huynh

4
มันหมายความว่าthisวัตถุมีค่ามากกว่าค่า Null สำหรับวัตถุประสงค์ในการเรียงลำดับการอ้างอิงวัตถุ null "น้อยกว่า" thisวัตถุ นั่นเป็นเพียงวิธีที่ฉันตัดสินใจที่จะกำหนดวิธีการจัดเรียงโมฆะ
Radarbob

18

// การจัดเรียงทั่วไปทั้งหมดสำหรับใช้กับ 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);
    }

4
หรือคุณรู้ไหมdata.OrderBy(). บิตง่ายกว่าที่ประดิษฐ์ล้อขึ้นใหม่
gunr2171

4
แนวคิดนี้จะทำงานกับวัตถุประเภทใดก็ได้ ที่ไหนเป็น OrderBy () ทำงานเฉพาะกับวัตถุที่พิมพ์อย่างยิ่ง
เจอร์

1
ขอบคุณมากจากความคิดของฉันการเรียงลำดับข้อมูลกริดที่ง่ายและใช้งานง่ายที่สุด!
kostas ch.

6

นี่คือวิธีส่วนขยาย 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)));
}

ฉันใช้สิ่งนี้ทำงานได้ดี ฉันเพิ่มพารามิเตอร์ "isAscending = true" หากต้องการเรียงลำดับจากมากไปน้อยเพียงสลับ x และ y ไปรอบ ๆ ภายในทั้งสองวิธีที่เรียกใช้ () ขอบคุณ
Rob L

หากคุณเพียงแค่รวบรวมนิพจน์คุณก็อาจยอมรับผู้รับมอบสิทธิ์เพื่อเริ่มต้นด้วย นอกจากนี้วิธีการนี้มีปัญหาที่สำคัญหากตัวเลือกทำให้เกิดผลข้างเคียงมีราคาแพงในการคำนวณหรือไม่ได้กำหนดไว้ การเรียงลำดับที่เหมาะสมตามนิพจน์ที่เลือกจำเป็นต้องเรียกใช้ตัวเลือกไม่เกินหนึ่งครั้งต่อรายการในรายการ
Servy

@Servy - เป็นคะแนนที่ถูกต้องทั้งหมด แต่ฉันจะซื่อสัตย์ฉันไม่แน่ใจว่าจะนำข้อเสนอแนะของคุณมาใช้อย่างไร (โดยเฉพาะการหยุดตัวเลือกจากสาเหตุของผลข้างเคียง ... ?) ฉันเปลี่ยนเป็นผู้ได้รับมอบหมาย หากคุณรู้วิธีทำการเปลี่ยนแปลงเหล่านั้นฉันยินดีที่จะให้คุณแก้ไขรหัสของฉัน
ปีเตอร์

3
@Peter คุณไม่สามารถป้องกันไม่ให้ผู้ร่วมประชุมก่อให้เกิดผลข้างเคียง สิ่งที่คุณสามารถทำได้คือให้แน่ใจว่าพวกเขาจะไม่เคยเรียกมากกว่าหนึ่งครั้งต่อวัตถุที่นี้หมายถึงการคำนวณค่าสำหรับแต่ละวัตถุการจัดเก็บวัตถุ / ที่คาดการณ์มูลค่าคู่แล้วเรียงลำดับว่า OrderByทำทั้งหมดนั้นภายใน
Servy

อีกวิธีที่ดีในการเขียนvoidวิธีการขยายในจิตวิญญาณนี้: static class Extensions { public static void SortBy<TSource, TKey>(this List<TSource> self, Func<TSource, TKey> keySelector) { self.SortBy(keySelector, Comparer<TKey>.Default); } public static void SortBy<TSource, TKey>(this List<TSource> self, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) { self.Sort((x, y) => comparer.Compare(keySelector(x), keySelector(y))); } }สามารถเสริมด้วยSortByDescendingวิธีการ @ ความคิดเห็น Servy ใช้กับรหัสของฉันเช่นกัน!
Jeppe Stig Nielsen


3
//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

การปรับปรุงเวอร์ชั่นของ Roger

ปัญหากับ GetDynamicSortProperty คือรับชื่อคุณสมบัติเท่านั้น แต่จะเกิดอะไรขึ้นถ้าใน GridView เราใช้ NavigationProperties มันจะส่งข้อยกเว้นเนื่องจากพบว่าเป็นโมฆะ

ตัวอย่าง:

"Employee.Company.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;
        }


    } 

3

คุณสามารถทำอะไรบางอย่างที่ทั่วไปมากขึ้นเกี่ยวกับการเลือกคุณสมบัติ แต่เฉพาะเจาะจงเกี่ยวกับประเภทที่คุณเลือกในกรณี 'สั่งซื้อ':

เขียนฟังก์ชั่นของคุณเป็นแบบทั่วไป:

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' แต่อาจให้เบาะแสว่าจะสามารถนำไปใช้ในรูปแบบทั่วไปได้อย่างไร


3

โปรดให้ฉันตอบคำถามโดย @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 ...
}



1

ขึ้นอยู่กับGenericTypeTea 's Comparer:
เราสามารถได้รับความยืดหยุ่นมากขึ้นโดยการเพิ่มการจัดเรียงธง:

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อย่างชัดเจน (แทนที่จะเป็นIComparer )
เพื่อตั้งค่าคุณสมบัติการเรียงลำดับ:

MyOrderingClass comparer = new MyOrderingClass();  
comparer.DateDescending = ...;  
comparer.OrderIdDescending = ...;  
orderList.Sort(comparer);  

1

ไม่มีคำตอบข้างต้นทั่วไปพอสำหรับฉันดังนั้นฉันทำอย่างนี้:

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 = # ของคุณสมบัติภายในวัตถุ


1

ใครทำงานกับประเภท nullable, ที่จำเป็นต้องใช้ValueCompareTo

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


0

จากประสิทธิภาพของมุมมองที่ดีที่สุดคือการใช้รายการที่เรียงลำดับเพื่อให้ข้อมูลถูกเรียงตามที่ถูกเพิ่มเข้ากับผลลัพธ์ วิธีการอื่น ๆ ต้องการการทำซ้ำอย่างน้อยหนึ่งครั้งในข้อมูลและส่วนใหญ่สร้างสำเนาของข้อมูลดังนั้นไม่เพียง แต่ประสิทธิภาพ แต่การใช้หน่วยความจำจะได้รับผลกระทบด้วย อาจไม่ใช่ปัญหากับองค์ประกอบสองสามร้อย แต่จะมีหลายพันรายการโดยเฉพาะอย่างยิ่งในบริการที่อาจมีการเรียงลำดับคำขอพร้อมกันจำนวนมากในเวลาเดียวกัน ดูที่ System.Collections.Generic namespace และเลือกคลาสที่มีการเรียงลำดับแทนที่จะเป็นรายการ

และหลีกเลี่ยงการใช้งานทั่วไปโดยใช้การสะท้อนเมื่อเป็นไปได้สิ่งนี้อาจทำให้เกิดปัญหาด้านประสิทธิภาพได้เช่นกัน


สิ่งนี้จะมีประสิทธิภาพมากขึ้นได้อย่างไร การแทรกข้อมูลในรายการที่เรียงลำดับคือ O (n) ดังนั้นการเพิ่ม n items คือ O (n ^ 2) พยายามเพิ่มรายการอะไรพร้อมกันหลายรายการ มีสถานการณ์เมื่อคุณมีรอบการทำงานของ CPU เพิ่มเติมที่จะเบิร์นในขณะที่กำลังเพิ่มรายการ แต่นี่ไม่ใช่วิธีแก้ปัญหาทั่วไปที่ดี
John La Rooy

0

สมมติว่าคุณมีรหัสต่อไปนี้ในรหัสนี้เรามีชั้นโดยสารที่มีคุณสมบัติสองสามอย่างที่เราต้องการเรียงลำดับตาม

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

    }
}

ดังนั้นคุณสามารถใช้โครงสร้างการเรียงลำดับของคุณโดยใช้ตัวแทนผู้แต่ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.