Een lijst sorteren<T> door een eigenschap in het object

Ik heb een klasse met de naam Orderdie eigenschappen heeft zoals OrderId, OrderDate, Quantityen Total. Ik heb een lijst van deze Orderklasse:

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

Nu wil ik de lijst sorteren op basis van één eigenschap van het Order-object, ik moet deze bijvoorbeeld sorteren op de besteldatum of bestel-ID.

Hoe kan ik dit doen in C#?


Antwoord 1, autoriteit 100%

De gemakkelijkste manier die ik kan bedenken is om Linq te gebruiken:

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

Antwoord 2, autoriteit 46%

Als u de lijst ter plekke moet sorteren, kunt u de Sortmethode, waarbij een Comparison<T>gemachtigde:

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

Als u liever een nieuwe, gesorteerde reeks maakt dan ter plaatse sorteert, kunt u OrderBymethode, zoals vermeld in de andere antwoorden.


Antwoord 3, autoriteit 11%

Om dit te doen zonder LINQ op .Net2.0:

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

Als je .Net3.0 gebruikt, dan is antwoordis wat u zoekt.

Als u op meerdere eigenschappen wilt sorteren, kunt u dit nog steeds doen binnen een gemachtigde. Bijvoorbeeld:

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

Dit geeft u oplopendedatums met aflopendeorderIds.

Ik zou echter niet aanraden om afgevaardigden vast te houden, omdat dit veel plaatsen betekent zonder hergebruik van code. Je moet een IComparerimplementeren en dat doorgeven aan je Sort-methode. Zie hier.

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

En om deze IComparer-klasse te gebruiken, moet u deze gewoon instantiëren en doorgeven aan uw Sort-methode:

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

Antwoord 4, autoriteit 6%

De eenvoudigste manier om een ​​lijst te bestellen is door OrderBy

te gebruiken

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

Als u op meerdere kolommen wilt bestellen, zoals het volgen van SQL-query’s.

ORDER BY OrderDate, OrderId

Om dit te bereiken kun je ThenBygebruiken zoals het volgende.

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

Antwoord 5, autoriteit 2%

Doen zonder Linq zoals je zei:

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

Noem dan gewoon .sort() op uw lijst met bestellingen


Antwoord 6

Een klassieke objectgeoriënteerde oplossing

Eerst moet ik knielen voor de geweldigheid van LINQ… Nu we dat uit de weg hebben geruimd

Een variatie op het antwoord van JimmyHoffa. Met generieke geneesmiddelen wordt de parameter CompareTotypeveilig.

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

Deze standaard sorteerbaarheid is natuurlijk herbruikbaar. Dat wil zeggen dat elke client de sorteerlogica niet redundant hoeft te herschrijven. Het verwisselen van de “1” en “-1” (of de logische operatoren, naar keuze) keert de sorteervolgorde om.


Antwoord 7

// Volledig generieke sortering voor gebruik met een rasterweergave

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

Antwoord 8

Hier is een generieke LINQ-extensiemethode die geen extra kopie van de lijst maakt:

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

Om het te gebruiken:

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

Ik heb onlangs deze extra gebouwd die een ICompare<U>accepteert, zodat je de vergelijking kunt aanpassen. Dit kwam goed van pas toen ik een natuurlijke string-sortering moest doen:

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

Antwoord 9

LINQ gebruiken

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

Antwoord 10

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

Antwoord 11

Laat me het antwoord van @LukeH aanvullen met wat voorbeeldcode, aangezien ik het heb getest, denk ik dat het voor sommigen nuttig kan zijn:

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

Antwoord 12

Een verbeterde versie van Roger.

Het probleem met GetDynamicSortProperty is dat we alleen de eigenschapsnamen krijgen, maar wat gebeurt er als we in de GridView NavigationProperties gebruiken? het zal een uitzondering verzenden, omdat het null vindt.

Voorbeeld:

“Employee.Company.Name; ” crasht… aangezien alleen “Naam” als parameter zijn waarde kan krijgen.

Hier is een verbeterde versie waarmee we kunnen sorteren op navigatie-eigenschappen.

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

Antwoord 13

U kunt iets generieker doen aan de selectie van eigenschappen, maar specifiek zijn over het type waaruit u selecteert, in uw geval ‘Bestellen’:

schrijf uw functie als een algemene:

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

en gebruik het dan als volgt:

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

Je kunt nog generieker zijn en een open type definiëren voor wat je wilt bestellen:

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

en gebruik het op dezelfde manier:

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

Wat een stomme onnodige complexe manier is om een ​​LINQ-stijl ‘OrderBy’ te doen,
Maar het kan u een idee geven van hoe het op een generieke manier kan worden geïmplementeerd


Antwoord 14

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

Antwoord 15

Maak gebruik van LiNQ OrderBy

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

Antwoord 16

Gebaseerd op GenericTypeTea‘s Comparer:
we kunnen meer flexibiliteit verkrijgen door sorteervlaggen toe te voegen:

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

In dit scenario moet u het expliciet maken als MyOrderingClass(in plaats van IComparer)
om de sorteereigenschappen in te stellen:

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

Antwoord 17

Geen van de bovenstaande antwoorden was algemeen genoeg voor mij, dus heb ik deze gemaakt:

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

Wees echter voorzichtig met enorme datasets. Het is een makkelijke code, maar het kan je in de problemen brengen als de collectie enorm is en het objecttype van de collectie een groot aantal velden heeft.
Runtime is NxM waarbij:

N = # elementen in verzameling

M = # van eigenschappen binnen object


Antwoord 18

Iedereen die werkt met nullable-typen, Valuemoet CompareTogebruiken.

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


Antwoord 19

Stel dat je de volgende code hebt, in deze code hebben we een Passenger-klasse met een aantal eigenschappen waarop we willen sorteren.

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

Dus je kunt je sorteerstructuur implementeren door Composition delegate te gebruiken.


Antwoord 20

Vanuit het oogpunt van prestaties is het het beste om een ​​gesorteerde lijst te gebruiken, zodat de gegevens worden gesorteerd wanneer ze aan het resultaat worden toegevoegd.
Andere benaderingen hebben ten minste één extra iteratie van gegevens nodig en de meeste maken een kopie van gegevens, zodat niet alleen de prestaties, maar ook het geheugengebruik wordt beïnvloed. Misschien geen probleem met een paar honderden elementen, maar met duizenden, vooral in services waar veel gelijktijdige verzoeken tegelijkertijd kunnen worden gesorteerd.
Bekijk System.Collections.Generic namespace en kies een klasse met sortering in plaats van List.

En vermijd generieke implementaties door waar mogelijk reflectie te gebruiken, dit kan ook prestatieproblemen veroorzaken.


Antwoord 21

hallo om even terug te komen op de vraag.
Als u de lijst van deze reeks wilt sorteren “1” “10” “100” “200” “2” “20” “3” “30” “300” en de gesorteerde items in deze vorm 1;2;3 wilt krijgen ;10;20;30;100;200;300 u kunt dit gebruiken:

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

en je kunt het in code achter gebruiken in deze vorm:

IComparer<String> comparerHandle = new OrderingAscending();
 yourList.Sort(comparerHandle);

Antwoord 22

  • Als u de ID moet sorteren die een tekenreeks is in de entiteit Vraag

  • Gebruik de sorteerfunctie en delegeer om de id te sorteren na het ontleden van de id
    waarde

   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((x, y) => int.Parse(x.Id, CultureInfo.CurrentCulture) - int.Parse(y.Id, CultureInfo.CurrentCulture));

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes