web-dev-qa-db-ja.com

Array.Copyは多次元配列で機能しますか?

このコードは正常に動作します:

_var newArray = new Rectangle[newHeight, newWidth];

for (int x = 0; x < newWidth; x++)
    for (int y = 0; y < newHeight; y++)
        newArray[y, x] = (x >= width) || (y >= height) ? Rectangle.Empty : tiles[y, x];
_

しかし、私はそれをArray.Copyで置き換えるのにあまり運がありません。基本的に、サイズ変更された配列の方が大きい場合は、端に空白の長方形が追加されるだけです。小さい場合は、端を切り落とします。

これを行うとき:

Array.Copy(tiles, newArray, newWidth * newHeight);

それは配列を混乱させ、その内容のすべてが無秩序になり、元のインデックスを保持しません。たぶん私はただの脳みそか何かを持っていますか?

25
Andrew Godfrey

はい。しかし、それはあなたがそれが機能していると思っている方法では機能しません。むしろ、それは各多次元配列を1次元配列と見なし(これは実際にはメモリ内にあるものであり、それらの上にいくつかの構造を配置して多次元と考えることができる単なるトリックです)、次に単一をコピーします次元構造。だからあなたが持っているなら

1 2 3
4 5 6

にコピーしたい

x x x x
x x x x

次に、最初の配列は

1 2 3 4 5 6

そして2番目は

x x x x x x x x

結果は

1 2 3 4 5 6 x x

としてあなたに表示されます

1 2 3 4
5 6 x x

とった?

36
jason

私はこのコードを使用します:

public static void ResizeBidimArrayWithElements<T>(ref T[,] original, int rows, int cols)
{

    T[,] newArray = new T[rows, cols];
    int minX = Math.Min(original.GetLength(0), newArray.GetLength(0));
    int minY = Math.Min(original.GetLength(1), newArray.GetLength(1));

    for (int i = 0; i < minX; ++i)
        Array.Copy(original, i * original.GetLength(1), newArray, i * newArray.GetLength(1), minY);

    original = newArray;

}

文字列の配列に対してこのように呼び出す

ResizeBidimArrayWithElements<string>(ref arrayOrigin, vNumRows, vNumCols);
6
Biggum

次の割り込みヒットの前に、バッファからデータを消費し、大きな保持配列にコピーする必要がありました。ループでのコピーはオプションではありませんでした。遅すぎる。すべてのコピーが完了するまで、結合されたデータの多次元構造は必要ありませんでした。これは、1つの次元配列に Buffer.BlockCopy() を実行し、次に多次元配列に再度コピーすることを意味します必要な構造を取得します。これは、テクニックとパフォーマンスを示すコード(コンソールで実行)です。

static class Program
{
    [STAThread]
    static void Main()
    {
        Stopwatch watch = new Stopwatch();

        const int width = 2;
        const int depth = 10 * 1000000;

        //  Create a large array of data
        Random r = new Random(100);
        int[,] data = new int[width, depth];
        for(int i = 0; i < width; i++)
        {
            for(int j = 0; j < depth; j++)
            {
                data[i, j] = r.Next();
            }
        }

        //  Block copy to a single dimension array
        watch.Start();
        int[] buffer = new int[width * depth];
        Buffer.BlockCopy(data, 0, buffer, 0, data.Length * sizeof(int));
        watch.Stop();
        Console.WriteLine("BlockCopy to flat array took {0}", watch.ElapsedMilliseconds);

        //  Block copy to multidimensional array
        int[,] data2 = new int[width, depth];
        watch.Start();
        Buffer.BlockCopy(buffer, 0, data2, 0,buffer.Length * sizeof(int));
        watch.Stop();
        Console.WriteLine("BlockCopy to 2 dimensional array took {0}", watch.ElapsedMilliseconds);


        //  Now try a loop based copy - eck!
        data2 = new int[width, depth];
        watch.Start();
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < depth; j++)
            {
                data2[i, j] = data[i, j];
            }
        }
        watch.Stop();
        Console.WriteLine("Loop-copy to 2 dimensional array took {0} ms", watch.ElapsedMilliseconds);
    }
}

出力:

BlockCopy to flat array took 14 ms
BlockCopy to 2 dimensional array took 28 ms
Loop-copy to 2 dimensional array took 149 ms
2
Steve K

次のように "Clone()"関数を使用するだけです。

これはあなたの配列リストです

object newArray = new object [row, column];

別の配列を作成するときは、次のコードを使用してください:

object[,] clonedArray = (object[,]) newArray.Clone();

シンプル!楽しんで!