2

我的程序大量使用Reverse,例如Array.Reverse(myArray,3,5)

我希望我的程序可以同时接受arrayList作为输入,所以我选择IList

但是,我找不到IListReverse.

有一种名为 的扩展方法Reverse,但是它产生IEnumerable流而不是就地重新排列。(我认为这需要更多的复制时间)

我想过使用cast,但又担心cast效率低下。

所以我该怎么做?

最坏的情况,我做了 2 个程序,1 个取数组,另一个取 List,然后重载?

4

5 回答 5

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;
            }
        }
    }
}
于 2012-07-02T16:10:15.400 回答
1

OOP 方式 - 制作一个包装器,重载它十几次:

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

只需添加范围检查/前提条件/不变量/等。此外,列表可能效率低下,因为它需要随机访问列表的内容,但我认为您无法使用“常规武器”(即不使用反射和直接内存操作)来解决它。

所以,我的建议 - 重载是要走的路。

于 2012-07-02T15:11:50.457 回答
0

如果您想要一个采用 IList 而不仅仅是 List 或 Array 的就地 Reverse 方法,您必须自己编写它。这不是一个特别复杂的算法,所以我想你有能力自己编写这样的方法。

于 2012-07-02T14:29:02.973 回答
0

Reverse()将产生一个IEnumerable直接基于列表的;不涉及复制。试一试,如果您只是迭代,它可能会更有效。

于 2012-07-02T13:59:21.613 回答
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
于 2012-07-02T14:02:14.200 回答