2

私のプログラムは集中的に使用しますReverse、例えばArray.Reverse(myArray,3,5)

私のプログラムが入力arrayとしてとの両方を受け入れることができるようにしたいので、私はListIList

IListしかし、と同じ方法が 見つかりませんでしたReverse

という名前の拡張メソッドが1つありますが、ストリームReverseは生成されますが、インプレース再配置は生成されません。IEnumerable(コピーに時間がかかると思います)

を使うことを考えcastましたが、それcastも非効率になるのではないかと心配していました。

だから、私は何をすべきですか?

最悪のシナリオでは、2つのプログラムを作成し、1つは配列を取得し、もう1つはリストを取得してからオーバーロードしますか?

4

5 に答える 5

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

このような方法で別のコレクションに似たクラスを逆にする必要があるたびに、オーバーロードを追加します。このアプローチは、非常に効果的で堅牢なシステム内部に依存していますが、多くの種類のオブジェクトを逆にする場合は冗長になる可能性があります。

I-can-do-it-myself-better-way:

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 に答える
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();
    }
}

LinqReverseメソッドも同じ方法で修正できます。

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 に答える
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 に答える
0

Reverse()IEnumerableリストに直接基づいて作成します。コピーは必要ありません。試してみてください。反復するだけの場合は、より効率的かもしれません。

于 2012-07-02T13:59:21.613 に答える
0

リストや配列だけでなく、IListを受け取るインプレースReverseメソッドが必要な場合は、自分で作成する必要があります。これは特に複雑なアルゴリズムではないので、そのようなメソッドを自分で作成できると思います。

于 2012-07-02T14:29:02.973 に答える