我的计划密集使用Reverse
,例如Array.Reverse(myArray,3,5)
我希望我的程序可以接受array
和List
作为输入,所以我选择IList
但是,我找不到与IList
相同的Reverse
方法。
有一个名为Reverse
的扩展方法,但它会生成IEnumerable
流但不会进行就地重新排列。 (我假设需要更多的复制时间)
我想过使用cast
,但担心cast
也会效率低下。
那么,我该怎么办?
最糟糕的情况是,我制作2个程序,1个接受数组,另一个接受List,然后重载?
答案 0 :(得分:1)
OOP-way - 制作一个包装器,重载十几次:
public void Reverse(Array arr, int index, int count)
{
Array.Reverse(arr, index, count);
}
public void Reverse<T>(List<T> lst, int index, int count)
{
lst.Reverse(index, count);
}
每当你需要以这种方式反转另一个类似于集合的类时,添加一个重载。这种方法依赖于系统内部,非常有效和强大,但如果您愿意撤销多种对象,可能会很冗长。
我灿做它自己,更好的方式:
static class Extensions
{
public static void Reverse(this IList target, int index, int count)
{
int right = index + count - 1;
int left = index;
while (right>left)
{
var tmp = target[left];
target[left] = target[right];
target[right] = tmp;
right--;
left++;
}
}
}
只需添加范围检查/前置条件/不变量/等。此外,列表可能效率低下,因为它需要随机访问列表的内容,但我认为你不能使用“常规武器”解决它(即不使用反射和直接内存操作)。
所以,我的建议 - 超载是要走的路。
答案 1 :(得分:1)
Linq Reverse()扩展方法错过了一个明显的优化,总是创建一个临时数组来存储元素以反转它们。这在列表或数组上使用太贵了。
如果你想要就地反转那么你可以编写一个扩展方法来选择正确的Reverse()方法:
public static class MyExtensions {
public static void Reverse<T>(this IList<T> source) {
if (source is List<T>) {
((List<T>)source).Reverse();
}
else if (source is T[]) {
Array.Reverse((T[])source);
}
else throw new ArgumentException();
}
}
你可以用同样的方法修复Linq Reverse方法:
public static class MyExtensions {
public static IEnumerable<T> Reverse<T>(this IEnumerable<T> source) {
if (source is IList<T>) {
var list = (IList<T>)source;
for (int ix = list.Count - 1; ix >= 0; --ix) {
yield return list[ix];
}
}
else {
foreach (var item in Enumerable.Reverse(source)) {
yield return item;
}
}
}
}
答案 2 :(得分:0)
Reverse()
将直接根据列表生成IEnumerable
;不涉及复制。尝试一下,如果你只是迭代它可能会更有效。
答案 3 :(得分:0)
Array.Reverse()
是静态的:
T[] arr = ...
Array.Reverse(arr); // in-place
List.Reverse
不是:
List<T> list = ...
list.Reverse(); // in-place too
还有一个LINQ扩展方法:
IList<T> ilist = ...
IEnumerable<T> e = ilist.AsEnumerable();
IEnumerable<T> result = e.Reverse(); // not in-place
答案 4 :(得分:0)
如果你想要一个采用IList的就地反向方法,而不仅仅是一个List或一个数组,你必须自己编写它。这不是一个特别复杂的算法,所以我想你自己能够编写这样的方法。