C #에서 IList 정렬
그래서 오늘 흥미로운 문제를 발견했습니다. 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가 아닌 List of T로 가져 가면 유형 안전성과 비교자를 구현하는 방법에 대한 더 많은 옵션을 얻을 수 있습니다.
@DavidMills가 받아 들인 대답은 꽤 좋지만 개선 될 수 있다고 생각합니다. 하나의 ComparisonComparer<T>
경우 프레임 워크에 이미 정적 메서드가 포함되어있는 경우 클래스 를 정의 할 필요가 없습니다 Comparer<T>.Create(Comparison<T>)
. 이 메서드는 IComparison
즉석 에서 생성하는 데 사용할 수 있습니다 .
또한, 캐스트 IList<T>
에 IList
어떤 위험 할 수있는 잠재력을 가지고있다. 내가 본 대부분의 경우 List<T>
어떤 구현 IList
이을 구현 하는 데 백그라운드에서 사용 IList<T>
되지만 이는 보장되지 않으며 부서지기 쉬운 코드로 이어질 수 있습니다.
마지막으로 오버로드 된 List<T>.Sort()
메서드에는 4 개의 서명이 있으며 그중 2 개만 구현됩니다.
List<T>.Sort()
List<T>.Sort(Comparison<T>)
List<T>.Sort(IComparer<T>)
List<T>.Sort(Int32, Int32, IComparer<T>)
아래 클래스 List<T>.Sort()
는 IList<T>
인터페이스에 대한 4 개의 서명을 모두 구현합니다 .
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;
}
}
The Cast function is just a reimplementation of the extension method that comes with 3.5 written as a normal static method. It is quite ugly and verbose unfortunately.
In VS2008, when I click on the service reference and select "Configure Service Reference", there is an option to choose how the client de-serializes lists returned from the service.
Notably, I can choose between System.Array, System.Collections.ArrayList and System.Collections.Generic.List
using System.Linq;
var yourList = SomeDAO.GetRandomThings();
yourList.ToList().Sort( (thing, randomThing) => thing.CompareThisProperty.CompareTo( randomThing.CompareThisProperty ) );
That's pretty !ghetto.
Found a good post on this and thought I'd share. Check it out HERE
Basically.
You can create the following class and IComparer Classes
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);
}
}
Then If you have an IList, you can sort it like this.
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());
But Checkout this site for more information... Check it out HERE
Is this a valid solution?
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();
The result was: IList B A C
List A B C
IList again A B C
참고URL : https://stackoverflow.com/questions/15486/sorting-an-ilist-in-c-sharp
'programing tip' 카테고리의 다른 글
HTTP 301과 308 상태 코드의 차이점은 무엇입니까? (0) | 2020.09.21 |
---|---|
NullInjectorError : AngularFirestore에 대한 공급자가 없습니다. (0) | 2020.09.21 |
PowerShell을 사용하는 파일 이름의 타임 스탬프 (0) | 2020.09.21 |
BitmapDrawable 더 이상 사용되지 않는 대안 (0) | 2020.09.21 |
파이썬에서 하나의 항목을 * 제외 *하는 모든 인덱스 (0) | 2020.09.21 |