etc./StackOverFlow

목록을 정렬하는 방법<T> 객체의 속성에 의해

청렴결백한 만능 재주꾼 2022. 3. 7. 11:53
반응형

질문자 :Shyju


OrderId , OrderDate , QuantityTotal 과 같은 속성이 있는 Order 라는 클래스가 있습니다. Order 클래스 목록이 있습니다.

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

Order 개체의 한 속성을 기반으로 목록을 정렬하려고 합니다. 예를 들어 주문 날짜 또는 주문 ID별로 정렬해야 합니다.

C#에서 이 작업을 수행하려면 어떻게 해야 합니까?



내가 생각할 수있는 가장 쉬운 방법은 Linq를 사용하는 것입니다.

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

Lazarus

목록을 제자리에서 정렬해야 하는 경우 Sort 메서드를 Comparison<T> 대리자를 전달할 수 있습니다.

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

제자리에서 정렬하는 대신 정렬된 새 시퀀스를 만드는 것을 선호하는 경우 다른 답변에서 언급한 대로 OrderBy


LukeH

.Net2.0에서 LINQ 없이 이 작업을 수행하려면 다음을 수행합니다.

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

.Net3.0에 있다면 LukeH의 대답 은 당신이 추구하는 것입니다.

여러 속성을 정렬하려면 여전히 대리자 내에서 정렬할 수 있습니다. 예를 들어:

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

djdd87

목록을 주문하는 가장 간단한 방법은 OrderBy

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

다음 SQL 쿼리와 같이 여러 열을 기준으로 정렬하려는 경우.

 ORDER BY OrderDate, OrderId

이를 달성하기 위해 다음과 같이 ThenBy

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

PSK

당신이 말했듯이 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()를 호출하면 됩니다.


Jimmy Hoffa

고전적인 객체 지향 솔루션

먼저 LINQ의 위대함에 경의를 표해야 합니다.... 이제 그 문제를 해결했습니다.

JimmyHoffa 답변의 변형입니다. 제네릭을 사용하면 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"(또는 원하는 논리 연산자)을 바꾸면 정렬 순서가 바뀝니다.


radarbob

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

roger

다음은 목록의 추가 복사본을 만들지 않는 일반 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))); }

Peter

링크 사용

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

Daniel A. White

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

Waqas Ahmed

일부 샘플 코드를 사용하여 @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 ... }

molbalga

로저 버전의 개선.

GetDynamicSortProperty의 문제는 속성 이름만 가져오지만 GridView에서 NavigationProperties를 사용하면 어떻게 될까요? null을 찾으므로 예외를 보냅니다.

예시:

"Employee.Company.Name; "이(가) 충돌합니다... "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; } }

Miguel Becerra

속성 선택에 대해 보다 일반적인 작업을 수행할 수 있지만 선택하는 유형(귀하의 경우 '주문')에 대해 구체적으로 지정할 수 있습니다.

함수를 일반 함수로 작성하십시오.

 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'를 수행하는 어리석고 불필요한 복잡한 방법이지만 일반적인 방식으로 구현하는 방법에 대한 단서를 제공할 수 있습니다.


Danny Mor

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

Jevgenij Kononov

LiNQ OrderBy

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

Pranay Rana

GenericTypeTea 의 비교자 기반:
정렬 플래그를 추가하여 더 많은 유연성을 얻을 수 있습니다.

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

이 시나리오에서는 명시적으로( IComparer 대신) MyOrderingClass 로 인스턴스화해야 합니다.
정렬 속성을 설정하려면 다음을 수행하십시오.

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

Jack Griffin

위의 답변 중 어느 것도 나에게 충분히 일반적이지 않았기 때문에 다음과 같이 만들었습니다.

 var someUserInputStringValue = "propertyNameOfObject ie 'Quantity' or 'Date'"; var SortedData = DataToBeSorted .OrderBy(m => m.GetType() .GetProperties() .First(n => n.Name == someUserInputStringValue) .GetValue(m, null)) .ToList();

그러나 방대한 데이터 세트에 주의하십시오. 쉬운 코드이지만 컬렉션이 거대하고 컬렉션의 개체 유형에 많은 수의 필드가 있는 경우 문제가 발생할 수 있습니다. 런타임은 NxM입니다. 여기서:

N = 컬렉션의 요소 수

M = 개체 내 속성 수


itcropper

nullable 형식으로 작업하는 모든 사람 CompareTo 를 사용하려면 Value 가 필요합니다.

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


Jude

다음 코드가 있다고 가정합니다. 이 코드에는 정렬 기준으로 삼고 싶은 몇 가지 속성이 있는 Passenger 클래스가 있습니다.

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

따라서 Composition 대리자를 사용하여 정렬 구조를 구현할 수 있습니다.


Seyedraouf Modarresi

성능 관점에서 가장 좋은 것은 정렬된 목록을 사용하여 결과에 데이터가 추가될 때 데이터가 정렬되도록 하는 것입니다. 다른 접근 방식은 데이터에 대해 최소 한 번 이상의 추가 반복이 필요하며 대부분 데이터 복사본을 생성하므로 성능뿐만 아니라 메모리 사용량에도 영향을 미칩니다. 수백 개의 요소에서는 문제가 되지 않을 수 있지만 수천 개의 요소에서는 특히 많은 동시 요청이 동시에 정렬을 수행할 수 있는 서비스에서 문제가 될 것입니다. System.Collections.Generic 네임스페이스를 살펴보고 List 대신 sorting이 있는 클래스를 선택하세요.

그리고 가능하면 리플렉션을 사용하는 일반 구현을 피하십시오. 이렇게 하면 성능 문제도 발생할 수 있습니다.


user3285954

안녕하세요, 질문으로 돌아오겠습니다. 이 시퀀스의 목록을 "1" "10" "100" "200" "2" "20" "3" "30" "300"으로 정렬하고 이 형식으로 정렬된 항목을 얻으려면 1;2;3 ;10;20;30;100;200;300 다음을 사용할 수 있습니다.

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

다음 형식의 코드 숨김에서 사용할 수 있습니다.

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

luka

  • Question 엔터티에서 문자열인 Id를 정렬해야 하는 경우

  • Sort 함수와 Delegate를 사용하여 Id 값을 파싱한 후 Id를 정렬합니다.

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

Dev-lop-er

출처 : http:www.stackoverflow.com/questions/3309188/how-to-sort-a-listt-by-a-property-in-the-object

반응형