문제

그래서 오늘 흥미로운 문제를 발견했습니다.IList를 반환하는 WCF 웹 서비스가 있습니다.내가 그것을 정리하고 싶을 때까지는 별로 큰 문제가 아니었습니다.

IList 인터페이스에는 정렬 메서드가 내장되어 있지 않은 것으로 나타났습니다.

나는 결국 ArrayList.Adapter(list).Sort(new MyComparer()) 문제를 해결하는 방법은 나에게 약간 "게토"처럼 보였습니다.

나는 확장 메서드를 작성하고 IList에서 상속하고 자체 Sort() 메서드를 구현하고 List로 캐스팅하는 등의 방법을 고민했지만 이들 중 어느 것도 지나치게 우아해 보이지 않았습니다.

제 질문은 IList를 정렬하는 우아한 솔루션을 갖고 있는 사람이 있느냐는 것입니다.

도움이 되었습니까?

해결책

LINQ To Objects를 사용하여 정렬하는 것은 어떻습니까?

당신이 가지고 있다고 말해보세요 IList<Car>, 그리고 그 차에는 Engine 속성에 따라 다음과 같이 정렬할 수 있을 것 같습니다.

from c in list
orderby c.Engine
select c;

편집하다:여기서 답변을 얻으려면 신속하게 처리해야 합니다.다른 답변과 약간 다른 구문을 제시했으므로 답변을 그대로 두겠습니다. 그러나 제시된 다른 답변도 동일하게 유효합니다.

다른 팁

LINQ를 사용할 수 있습니다.

using System.Linq;

IList<Foo> list = new List<Foo>();
IEnumerable<Foo> sortedEnum = list.OrderBy(f=>f.Bar);
IList<Foo> sortedList = sortedEnum.ToList();

이 질문은 제가 블로그 게시물을 쓰도록 영감을 주었습니다. http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/

이상적으로는 .NET Framework에 IList<T>를 허용하는 정적 정렬 방법이 포함되지만 차선책은 자신만의 확장 방법을 만드는 것입니다.List<T>처럼 IList<T>를 정렬할 수 있는 몇 가지 메서드를 만드는 것은 그리 어렵지 않습니다.보너스로 동일한 기술을 사용하여 LINQ OrderBy 확장 메서드를 오버로드할 수 있으므로 List.Sort, IList.Sort 또는 IEnumerable.OrderBy를 사용하든 정확히 동일한 구문을 사용할 수 있습니다.

public static class SortExtensions
{
    //  Sorts an IList<T> in place.
    public static void Sort<T>(this IList<T> list, Comparison<T> comparison)
    {
        ArrayList.Adapter((IList)list).Sort(new ComparisonComparer<T>(comparison));
    }

    // Convenience method on IEnumerable<T> to allow passing of a
    // Comparison<T> delegate to the OrderBy method.
    public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, Comparison<T> comparison)
    {
        return list.OrderBy(t => t, new ComparisonComparer<T>(comparison));
    }
}

// Wraps a generic Comparison<T> delegate in an IComparer to make it easy
// to use a lambda expression for methods that take an IComparer or IComparer<T>
public class ComparisonComparer<T> : IComparer<T>, IComparer
{
    private readonly Comparison<T> _comparison;

    public ComparisonComparer(Comparison<T> comparison)
    {
        _comparison = comparison;
    }

    public int Compare(T x, T y)
    {
        return _comparison(x, y);
    }

    public int Compare(object o1, object o2)
    {
        return _comparison((T)o1, (T)o2);
    }
}

이러한 확장을 사용하면 목록처럼 IList를 정렬할 수 있습니다.

IList<string> iList = new []
{
    "Carlton", "Alison", "Bob", "Eric", "David"
};

// Use the custom extensions:

// Sort in-place, by string length
iList.Sort((s1, s2) => s1.Length.CompareTo(s2.Length));

// Or use OrderBy()
IEnumerable<string> ordered = iList.OrderBy((s1, s2) => s1.Length.CompareTo(s2.Length));

게시물에 더 많은 정보가 있습니다. http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/

당신은 내 생각에 그런 일을 해야 할 것입니다(더 구체적인 유형으로 변환).

ArrayList가 아닌 T 목록으로 가져가면 유형 안전성과 비교자 구현 방법에 대한 더 많은 옵션을 얻을 수 있습니다.

@DavidMills의 답변은 꽤 훌륭하지만 개선될 수 있다고 생각합니다.우선, 정의할 필요가 없습니다. ComparisonComparer<T> 프레임워크에 이미 정적 메서드가 포함되어 있는 경우 클래스 Comparer<T>.Create(Comparison<T>).이 방법을 사용하여 IComparison 즉석에서.

또한, 캐스팅 IList<T> 에게 IList 위험할 가능성이 있는 것입니다.제가 본 대부분의 경우, List<T> 구현하는 IList 구현하기 위해 뒤에서 사용됩니다. IList<T>, 그러나 이는 보장되지 않으며 취약한 코드로 이어질 수 있습니다.

마지막으로 과부하 List<T>.Sort() 메소드에는 4개의 시그니처가 있으며 그 중 2개만 구현됩니다.

  1. List<T>.Sort()
  2. List<T>.Sort(Comparison<T>)
  3. List<T>.Sort(IComparer<T>)
  4. List<T>.Sort(Int32, Int32, IComparer<T>)

아래 클래스는 4가지를 모두 구현합니다. List<T>.Sort() 에 대한 서명 IList<T> 상호 작용:

using System;
using System.Collections.Generic;

public static class IListExtensions
{
    public static void Sort<T>(this IList<T> list)
    {
        if (list is List<T>)
        {
            ((List<T>)list).Sort();
        }
        else
        {
            List<T> copy = new List<T>(list);
            copy.Sort();
            Copy(copy, 0, list, 0, list.Count);
        }
    }

    public static void Sort<T>(this IList<T> list, Comparison<T> comparison)
    {
        if (list is List<T>)
        {
            ((List<T>)list).Sort(comparison);
        }
        else
        {
            List<T> copy = new List<T>(list);
            copy.Sort(comparison);
            Copy(copy, 0, list, 0, list.Count);
        }
    }

    public static void Sort<T>(this IList<T> list, IComparer<T> comparer)
    {
        if (list is List<T>)
        {
            ((List<T>)list).Sort(comparer);
        }
        else
        {
            List<T> copy = new List<T>(list);
            copy.Sort(comparer);
            Copy(copy, 0, list, 0, list.Count);
        }
    }

    public static void Sort<T>(this IList<T> list, int index, int count,
        IComparer<T> comparer)
    {
        if (list is List<T>)
        {
            ((List<T>)list).Sort(index, count, comparer);
        }
        else
        {
            List<T> range = new List<T>(count);
            for (int i = 0; i < count; i++)
            {
                range.Add(list[index + i]);
            }
            range.Sort(comparer);
            Copy(range, 0, list, index, count);
        }
    }

    private static void Copy<T>(IList<T> sourceList, int sourceIndex,
        IList<T> destinationList, int destinationIndex, int count)
    {
        for (int i = 0; i < count; i++)
        {
            destinationList[destinationIndex + i] = sourceList[sourceIndex + i];
        }
    }
}

용법:

class Foo
{
    public int Bar;

    public Foo(int bar) { this.Bar = bar; }
}

void TestSort()
{
    IList<int> ints = new List<int>() { 1, 4, 5, 3, 2 };
    IList<Foo> foos = new List<Foo>()
    {
        new Foo(1),
        new Foo(4),
        new Foo(5),
        new Foo(3),
        new Foo(2),
    };

    ints.Sort();
    foos.Sort((x, y) => Comparer<int>.Default.Compare(x.Bar, y.Bar));
}

여기서 아이디어는 기본 기능을 활용하는 것입니다. List<T> 가능할 때마다 정렬을 처리합니다.다시 말하지만, 대부분 IList<T> 내가 본 구현에서는 이것을 사용합니다.기본 컬렉션이 다른 유형인 경우 새 인스턴스를 만드는 것으로 대체됩니다. List<T> 입력 목록의 요소를 사용하여 정렬을 수행한 다음 결과를 다시 입력 목록에 복사합니다.이는 입력 목록이 다음을 구현하지 않는 경우에도 작동합니다. IList 상호 작용.

원래 게시물에 설명된 정확한 문제에 대한 해결책을 찾는 동안 이 스레드를 발견했습니다.그러나 그 어떤 대답도 내 상황에 완전히 부합하지 않았습니다.Brody의 대답은 꽤 가깝습니다.제가 찾은 상황과 해결책은 다음과 같습니다.

나는 NHibernate에 의해 반환된 동일한 유형의 두 개의 IList를 가지고 있으며 두 개의 IList를 하나로 나타내므로 정렬이 필요합니다.

Brody가 말했듯이 나는 IList의 유형인 개체(ReportFormat)에 ICompare를 구현했습니다.

 public class FormatCcdeSorter:IComparer<ReportFormat>
    {
       public int Compare(ReportFormat x, ReportFormat y)
        {
           return x.FormatCode.CompareTo(y.FormatCode);
        }
    }

그런 다음 병합된 IList를 동일한 유형의 배열로 변환합니다.

ReportFormat[] myReports = new ReportFormat[reports.Count]; //reports is the merged IList

그런 다음 배열을 정렬합니다.

Array.Sort(myReports, new FormatCodeSorter());//sorting using custom comparer

1차원 배열은 인터페이스를 구현하기 때문에 System.Collections.Generic.IList<T>, 배열은 원래 IList처럼 사용할 수 있습니다.

그리드 정렬에 유용합니다. 이 방법은 속성 이름을 기준으로 목록을 정렬합니다.예를 따르십시오.

    List<MeuTeste> temp = new List<MeuTeste>();

    temp.Add(new MeuTeste(2, "ramster", DateTime.Now));
    temp.Add(new MeuTeste(1, "ball", DateTime.Now));
    temp.Add(new MeuTeste(8, "gimm", DateTime.Now));
    temp.Add(new MeuTeste(3, "dies", DateTime.Now));
    temp.Add(new MeuTeste(9, "random", DateTime.Now));
    temp.Add(new MeuTeste(5, "call", DateTime.Now));
    temp.Add(new MeuTeste(6, "simple", DateTime.Now));
    temp.Add(new MeuTeste(7, "silver", DateTime.Now));
    temp.Add(new MeuTeste(4, "inn", DateTime.Now));

    SortList(ref temp, SortDirection.Ascending, "MyProperty");

    private void SortList<T>(
    ref List<T> lista
    , SortDirection sort
    , string propertyToOrder)
    {
        if (!string.IsNullOrEmpty(propertyToOrder)
        && lista != null
        && lista.Count > 0)
        {
            Type t = lista[0].GetType();

            if (sort == SortDirection.Ascending)
            {
                lista = lista.OrderBy(
                    a => t.InvokeMember(
                        propertyToOrder
                        , System.Reflection.BindingFlags.GetProperty
                        , null
                        , a
                        , null
                    )
                ).ToList();
            }
            else
            {
                lista = lista.OrderByDescending(
                    a => t.InvokeMember(
                        propertyToOrder
                        , System.Reflection.BindingFlags.GetProperty
                        , null
                        , a
                        , null
                    )
                ).ToList();
            }
        }
    }
try this  **USE ORDER BY** :

   public class Employee
    {
        public string Id { get; set; }
        public string Name { get; set; }
    }

 private static IList<Employee> GetItems()
        {
            List<Employee> lst = new List<Employee>();

            lst.Add(new Employee { Id = "1", Name = "Emp1" });
            lst.Add(new Employee { Id = "2", Name = "Emp2" });
            lst.Add(new Employee { Id = "7", Name = "Emp7" });
            lst.Add(new Employee { Id = "4", Name = "Emp4" });
            lst.Add(new Employee { Id = "5", Name = "Emp5" });
            lst.Add(new Employee { Id = "6", Name = "Emp6" });
            lst.Add(new Employee { Id = "3", Name = "Emp3" });

            return lst;
        }

**var lst = GetItems().AsEnumerable();

            var orderedLst = lst.OrderBy(t => t.Id).ToList();

            orderedLst.ForEach(emp => Console.WriteLine("Id - {0} Name -{1}", emp.Id, emp.Name));**

변환하세요 IList ~ 안으로 List<T> 또는 다른 일반 컬렉션을 사용하여 쉽게 쿼리/정렬할 수 있습니다. System.Linq 네임스페이스(다양한 확장 메소드를 제공합니다)

다음은 더 강력한 타이핑을 사용한 예입니다.그래도 그것이 반드시 최선의 방법인지는 확실하지 않습니다.

static void Main(string[] args)
{
    IList list = new List<int>() { 1, 3, 2, 5, 4, 6, 9, 8, 7 };
    List<int> stronglyTypedList = new List<int>(Cast<int>(list));
    stronglyTypedList.Sort();
}

private static IEnumerable<T> Cast<T>(IEnumerable list)
{
    foreach (T item in list)
    {
        yield return item;
    }
}

Cast 함수는 일반적인 정적 메서드로 작성된 3.5와 함께 제공되는 확장 메서드를 다시 구현한 것입니다.불행히도 매우 추악하고 장황합니다.

VS2008에서는 서비스 참조를 클릭하고 "서비스 참조 구성"을 선택하면 클라이언트가 서비스에서 반환된 목록을 역직렬화하는 방법을 선택할 수 있는 옵션이 있습니다.

특히 System.Array, System.Collections.ArrayList 및 System.Collections.Generic.List 중에서 선택할 수 있습니다.

using System.Linq;

var yourList = SomeDAO.GetRandomThings();
yourList.ToList().Sort( (thing, randomThing) => thing.CompareThisProperty.CompareTo( randomThing.CompareThisProperty ) );

정말 멋지네요!게토.

이에 대한 좋은 게시물을 발견하고 공유하고 싶다고 생각했습니다. 여기서 확인해보세요

원래.

다음 클래스와 IComparer 클래스를 만들 수 있습니다.

public class Widget {
    public string Name = string.Empty;
    public int Size = 0;

    public Widget(string name, int size) {
    this.Name = name;
    this.Size = size;
}
}

public class WidgetNameSorter : IComparer<Widget> {
    public int Compare(Widget x, Widget y) {
        return x.Name.CompareTo(y.Name);
}
}

public class WidgetSizeSorter : IComparer<Widget> {
    public int Compare(Widget x, Widget y) {
    return x.Size.CompareTo(y.Size);
}
}

그런 다음 IList가 있으면 다음과 같이 정렬할 수 있습니다.

List<Widget> widgets = new List<Widget>();
widgets.Add(new Widget("Zeta", 6));
widgets.Add(new Widget("Beta", 3));
widgets.Add(new Widget("Alpha", 9));

widgets.Sort(new WidgetNameSorter());
widgets.Sort(new WidgetSizeSorter());

하지만 자세한 내용은 이 사이트를 확인하세요... 여기서 확인해보세요

이것이 유효한 해결책입니까?

        IList<string> ilist = new List<string>();
        ilist.Add("B");
        ilist.Add("A");
        ilist.Add("C");

        Console.WriteLine("IList");
        foreach (string val in ilist)
            Console.WriteLine(val);
        Console.WriteLine();

        List<string> list = (List<string>)ilist;
        list.Sort();
        Console.WriteLine("List");
        foreach (string val in list)
            Console.WriteLine(val);
        Console.WriteLine();

        list = null;

        Console.WriteLine("IList again");
        foreach (string val in ilist)
            Console.WriteLine(val);
        Console.WriteLine();

결과는 다음과 같습니다.ILIST B A C.

A B c

다시 ilist A B c

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top