programing

오브젝트 내의 속성별로 목록을 정렬하는 방법

telebox 2023. 4. 17. 21:41
반응형

오브젝트 내의 속성별로 목록을 정렬하는 방법

는 '수업하다'라는 수업이 있어요.Order 있습니다.OrderId,OrderDate,Quantity , , , , 입니다.Total가 가지고 있습니다.Order 링크:

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

는 1의 .Orderobject idobject 예를 들어 주문 날짜 또는 주문 ID를 기준으로 합니다.

C#에서는 어떻게 하면 좋을까요?

가장 쉬운 방법은 Linq를 사용하는 것입니다.

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

목록을 정렬해야 할 경우 위임자를 전달하는 방법을 사용할 수 있습니다.

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

내부 정렬이 아닌 정렬된 새 시퀀스를 작성하는 경우 다른 답변에서 설명한 것처럼 LINQ의 방법을 사용할 수 있습니다.

위에서 LINQ를 사용하지 않고 이를 수행하려면Net2.0:

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

하고 있는 경우.넷3.0, 그럼 루크H의 은 당신이 원하는 겁니다.

여러 속성을 정렬하려면 위임자 내에서 정렬할 수 있습니다.예를 들어 다음과 같습니다.

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

이렇게 하면 내림차순 ID가 있는 오름차순 날짜가 표시됩니다.

코드를 많은 하지 않습니다. 경우 '하다'를 실행해야 .IComparer의 리리 your your your your your your your 에 전달해 .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 클래스를 사용하려면 ICMPARER 클래스를 인스턴스화하여 Sort 메서드에 전달합니다.

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

은 목록을 정렬하는 입니다.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();

당신이 말한 것처럼 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()를 호출해 주세요.

기존 객체 지향 솔루션

먼저 LINQ의 놀라움에 무릎을 꿇어야 합니다.이제 그 문제를 해결했으니까

지미호파하면 Generic은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"(또는 논리 연산자, 선택 사항)을 바꾸면 정렬 순서가 반대로 됩니다.

// 그리드 뷰에서 사용하기 위한 완전 일반 정렬

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

LINQ 사용

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

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

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

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

타입으로 하는 모든 , " " " " "Value를 사용하려면 , 를 사용할 필요가 있습니다.CompareTo.

objListOrder.Sort((x, y) => x.YourNullableType.Value.CompareTo(y.YourNullableType.Value));
//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;

Roger의 버전을 개량한 것입니다.

GetDynamicSortProperty의 문제는 속성 이름만 얻는다는 것입니다만, GridView에서 NavigationProperties를 사용하면 어떻게 됩니까?null이 발견되었기 때문에 예외를 보냅니다.

예:

종업원.회사.이름; "이 충돌합니다...파라미터로서 「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;
        }


    } 

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

함수를 일반 함수로 적습니다.

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

var obj = db.Items.Where...

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

다음과 같은 코드가 있다고 가정해 보겠습니다. 이 코드에는 몇 가지 속성을 기준으로 정렬할 수 있는 승객 클래스가 있습니다.

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

    }
}

따라서 구성 위임자를 사용하여 정렬 구조를 구현할 수 있습니다.

은 제가 만든 입니다.List<T>.

" " " 를 합니다.OrderBy의 of의 List<T>그런 다음 원래 목록의 각 인덱스를 순서 목록의 인덱스와 동일한 인덱스로 설정합니다.

public static class ListExtensions {
    public static void SortBy<T>(this List<T> list, string property, bool reverse = false) {
        List<T> ordered = list.OrderBy(obj => obj.GetType().GetProperty(property).GetValue(obj, null)).ToList();
            
        for (int i = 0; i < list.Count; i++)
            list[i] = reverse ? ordered[list.Count - 1 - i] : ordered[i];
    }
}

Name합니다.testList

//For normal sorting order
testList.SortBy("Name");
//For reverse sorting order
testList.SortBy("Name", true);

을 추천합니다.SortBy ★★★★★★★★★★★★★★★★★★★★.Prefix_SortBy를 Import할 발생할 수 있는 다른 라이브러리를 Import할 경우 발생할 수 있는 충돌을 방지하기 위해

이 방법은 알파벳과 숫자 순으로 정렬하는 데 효과가 있는 것으로 알고 있습니다.정렬 기능은 제한적일 수 있지만 조작은 매우 간단합니다.

이것에 중대한 결함이나 문제가 있으면, 3개월 정도 C#를 프로그래밍하고 있다고 전해 주세요.

안부 전합니다

LiNQ 활용

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

Generic Type Tea의 Comparr를 기반으로 합니다.
플래그를.

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

이 시나리오에서는 명시적으로 My Ordering Class(IComparer가 아닌)로 인스턴스화해야 합니다.
정렬 속성을 설정하려면 다음 절차를 수행합니다.

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

위의 답변 중 어느 것도 충분히 일반적인 것이 아니었기 때문에 다음과 같이 했습니다.

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 = 개체 내 속성 수

  • 질문 엔티티에서 문자열인 ID를 정렬해야 하는 경우

  • Id 값을 해석한 후 Id를 정렬하려면 Sort 함수 및 위임자를 사용합니다.

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

성능 관점에서 가장 좋은 방법은 데이터가 결과에 추가될 때 정렬되도록 정렬된 목록을 사용하는 것입니다.다른 접근 방식에서는 데이터에 대해 적어도 한 번 더 반복해야 하며 대부분 데이터 복사본을 생성하므로 성능뿐만 아니라 메모리 사용률도 영향을 받습니다.수백 개의 요소에는 문제가 없지만 수천 개의 요소에는 문제가 있을 수 있습니다. 특히 여러 동시 요청이 동시에 정렬되는 서비스에서는 더욱 그렇습니다.시스템을 살펴봅니다.컬렉션일반 네임스페이스이며 목록 대신 정렬이 포함된 클래스를 선택합니다.

또한 가능한 한 반성을 사용한 일반적인 구현은 피하십시오. 이 경우에도 성능 문제가 발생할 수 있습니다.

안녕, 다시 질문으로 돌아오기 위해.이 시퀀스 "1" "10" "100" "200" "2" "20" "3" "30" "300"을 정렬하고 정렬된 항목을 1;2;3;10;20;100;200" 형식으로 가져오려면 다음을 사용합니다.

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

언급URL : https://stackoverflow.com/questions/3309188/how-to-sort-a-listt-by-a-property-in-the-object

반응형