lom*_*axx 85 c# sorting generics ilist
所以今天我遇到了一个有趣的问题.我们有一个返回IList的WCF Web服务.在我想对它进行排序之前,这并不是什么大问题.
结果是IList接口没有内置的排序方法.
我最终使用该ArrayList.Adapter(list).Sort(new MyComparer())
方法来解决问题,但它对我来说似乎有点"贫民窟".
我玩弄了一个扩展方法,也继承了IList并实现了我自己的Sort()方法以及转换为List,但这些方法似乎都不太优雅.
所以我的问题是,有没有人有一个优雅的解决方案来排序IList
Mar*_*ade 63
您可以使用LINQ:
using System.Linq;
IList<Foo> list = new List<Foo>();
IEnumerable<Foo> sortedEnum = list.OrderBy(f=>f.Bar);
IList<Foo> sortedList = sortedEnum.ToList();
Run Code Online (Sandbox Code Playgroud)
Dav*_*lls 56
这个问题激发了我写博客的一篇文章: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);
}
}
Run Code Online (Sandbox Code Playgroud)
使用这些扩展,像对待List一样对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));
Run Code Online (Sandbox Code Playgroud)
帖子中有更多信息:http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/
Bra*_*ach 54
如何使用LINQ To Objects为您排序?
假设你有IList<Car>
,并且汽车Engine
有财产,我相信你可以按如下方式排序:
from c in list
orderby c.Engine
select c;
Run Code Online (Sandbox Code Playgroud)
编辑:你需要快速在这里得到答案.由于我提出了与其他答案略有不同的语法,我将留下我的答案 - 但是,所提出的其他答案同样有效.
@DavidMills 接受的答案非常好,但我认为它可以改进。ComparisonComparer<T>
其一,当框架已经包含静态方法时,无需定义类Comparer<T>.Create(Comparison<T>)
。此方法可用于IComparison
动态创建。
此外,它所施放的东西IList<T>
也IList
有潜在的危险。在我见过的大多数情况下,List<T>
which ImplementsIList
是在幕后使用来实现的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> listImpl)
{
listImpl.Sort();
}
else
{
var 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> listImpl)
{
listImpl.Sort(comparison);
}
else
{
var 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> listImpl)
{
listImpl.Sort(comparer);
}
else
{
var 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> listImpl)
{
listImpl.Sort(index, count, comparer);
}
else
{
var 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];
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
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));
}
Run Code Online (Sandbox Code Playgroud)
这里的想法是List<T>
尽可能利用底层的功能来处理排序。同样,IList<T>
我见过的大多数实现都使用它。如果基础集合是不同类型,则回退到使用List<T>
输入列表中的元素创建新实例,使用它进行排序,然后将结果复制回输入列表。即使输入列表没有实现该IList
接口,这也将起作用。