Ik heb een klasse met de naam Order
die eigenschappen heeft zoals OrderId
, OrderDate
, Quantity
en Total
. Ik heb een lijst van deze Order
klasse:
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 Sort
methode, 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 OrderBy
methode, 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 IComparer
implementeren 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 ThenBy
gebruiken 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 CompareTo
typeveilig.
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, Value
moet CompareTo
gebruiken.
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));