37

This code works fine:

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];

But I am not having much luck replacing it with Array.Copy. Basically, if the resized array is larger it just adds blank rectangles to the edges. If it is smaller then it should just cut off the edges.

When doing this:

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

It messes up the array and all of its contents become disordered and do not retain their original index. Maybe I'm just having a brainfart or something?

0

4 Answers 4

56

Yes. However, it doesn't work the way you are thinking it works. Rather, it thinks of each mutlidimensional array as a single-dimensional array (which is actually what they are in memory, it's just a trick that lets us place some structure on top of them to think of them as multidimensional) and then copies the single-dimensional structures. So if you have

1 2 3
4 5 6

and want to copy it into

x x x x
x x x x

then it will think of the first array as

1 2 3 4 5 6

and the second as

x x x x x x x x

and the result will be

1 2 3 4 5 6 x x

which will appear to you as

1 2 3 4
5 6 x x

Got it?

Sign up to request clarification or add additional context in comments.

6 Comments

Whoa, thank you. I finally get how to use it. All this time I never thought it would work for multidimensional arrays
I understand, but is there any way to fix it so that it works properly?
I'm all for code reuse, but is there a specific reason that you want to replace your working 3 lines of code?
Alright, thanks! I was just wondering because my program is done and I'm just refactoring right now to make it look pretty O_O
Keep in mind that although Array.Copy doesn't require its source and destination array to be of same length in each dimension, it does require both to be of same Rank (number of dimensions). Buffer.BlockCopy does not have this restriction.
|
6

I use this code:

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;

}

calling like this for array of strings

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

Comments

4

I had a need to consume data from a buffer and copy off to a large holding array before the next interrupt hit. Copying in a loop wasn't an option; far too slow. I didn't need the multidimensional structure of the combined data until all of the copying was done, this meant I could Buffer.BlockCopy() to a single dimension array, then copy again onto a multidimensional array to obtain the required structure. Here's some code (run it in a console) that will demonstrate the technique as well as the performance.

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

Output:

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

1 Comment

The example doesn't use the stopwatches right. If you Stop() and then Start() the watch will continue where it last stopped. What you meant to use is Restart(). As a result of this error the "BlockCopy to 2 dimensional array" duration is actually the current output minus the flat array. Meaning both are as fast (14ms). The loop copy is in turn 28ms faster than the output presented.
3

Simple use the "Clone()" function like the following:

This is your array list

object newArray = new object [row, column];

When you are creating another Array just use this code:

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

Simple! Have fun!

1 Comment

I think it's not correct because Clone() only make a new pointer which points to the current memory of old array. It means if you change anything in new array, it'll be applied back to original array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.