Работи ли 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);

Това обърква масива и цялото му съдържание става неподредено и не запазва оригиналния си индекс. Може би просто имам мозъчен удар или нещо подобно?


person Andrew Godfrey    schedule 01.09.2011    source източник


Отговори (4)


да Това обаче не работи по начина, по който си мислите, че работи. По-скоро той мисли за всеки многоизмерен масив като за едноизмерен масив (което всъщност е това, което те са в паметта, това е просто трик, който ни позволява да поставим някаква структура върху тях, за да ги мислим за многоизмерни) и след това копира единичния -размерни структури. Така че, ако имате

1 2 3
4 5 6

и искате да го копирате в

x x x x
x x x x

тогава ще мисли за първия масив като

1 2 3 4 5 6

а вторият като

x x x x x x x x

и резултатът ще бъде

1 2 3 4 5 6 x x

което ще ви изглежда като

1 2 3 4
5 6 x x

Схванах го?

person jason    schedule 01.09.2011
comment
Уау, благодаря ти. Най-накрая разбрах как да го използвам. През цялото това време никога не съм мислил, че ще работи за многомерни масиви - person Martheen; 01.09.2011
comment
Разбирам, но има ли начин да го поправя, така че да работи правилно? - person Andrew Godfrey; 01.09.2011
comment
Аз съм напълно за повторното използване на кода, но има ли конкретна причина, поради която искате да замените работните си 3 реда код? - person Paul Walls; 01.09.2011
comment
@Andrew Godfrey: Работи правилно; просто не работи по начина, по който мислите, че трябва да работи. Няма начин да го накарате да работи така, както смятате, че трябва да работи. Array.Copy е предназначен да бъде светкавично бърз и това означава да се възползвате от факта, че копирането на линейно-последователни парчета памет е светкавично бързо. Искате да копирате по начин, който не е линейно съседен. Array.Copy не беше предназначен за тази работа. Трябва да намерите нещо друго, което прави това вместо вас. По-специално, кодът, който вече сте написали, прави точно това, което искате. Използваи го. - person jason; 01.09.2011
comment
Добре, благодаря! Просто се чудех, защото програмата ми е готова и в момента правя рефакторинг, за да изглежда добре O_O - person Andrew Godfrey; 01.09.2011
comment
Имайте предвид, че въпреки че Array.Copy не изисква масивът източник и местоназначение да са с еднаква дължина във всяко измерение, той изисква и двете да бъдат с един и същ Ранг (брой измерения). Buffer.BlockCopy няма това ограничение. - person rwong; 15.03.2014

Използвам този код:

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);
person Biggum    schedule 08.05.2013

Имах нужда да консумирам данни от буфер и да ги копирам в голям холдинг масив преди следващото прекъсване. Копирането в цикъл не беше опция; твърде бавен. Нямах нужда от многоизмерната структура на комбинираните данни, докато не беше направено цялото копиране, това означаваше, че мога да 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
person scubasteve    schedule 09.10.2015

Просто използвайте функцията "Clone()", както следва:

Това е вашият списък с масиви

object newArray = new object [row, column];

Когато създавате друг масив, просто използвайте този код:

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

просто! Забавлявай се!

person Gláucio Leonardo Sant'ana    schedule 17.05.2018