简体   繁体   中英

c# assign 1 dimensional array to 2 dimensional array with shifting values

I have a vector (1D array) of double values, say X. I need to copy this vector of values into a matrix (2D array), say Y, such that the first row of Y is the same as X transposed, the second row is the same as X shifted one value to the left, the third row of Y is the same as X shifted two values to the left and so on.

For example,

X = { 1.0, 2.0. 3.0, 4.0, 5.0 }

and I need

Y =  1.0  2.0  3.0  4.0  5.0
     2.0  3.0  4.0  5.0  0.0
     3.0  4.0  5.0  0.0  0.0
     4.0  5.0  0.0  0.0  0.0
     5.0  0.0  0.0  0.0  0.0

Some time ago Mathew Finlay posted code for copying 1D array to a 2D array for value types. I have modified the code as follows:

for (int targetRow = 0; targetRow < N; targetRow++)
{
    Buffer.BlockCopy
    (
        X,                                                    // 1D source array
        0,                                                    // source array offset
        Y,                                                    // 2D target (destination) array
        targetRow * Y.GetLength(targetRow) * sizeof(double),  // target array offset
        X.Length * sizeof(double)                             // count
    );
}

I am not sure if this will do the trick and more importantly, whether this is the best way of doing this. This is part of a larger code and this part needs to be fast and efficient as the vector X and the matrix Y can get very large.

Also, to complicate things a bit more, I may sometines not require the full length (all the values) of vector X but only part of it so the matrix Y could be N x M where M <= N. I am not sure how to handle this in the code above.

Thank you in advance for any help or suggestions you may be able to provide.

EDIT: For those interested, here are some performance results.

I ran some speed tests on the two types of code suggested here (looping and Buffer.BlockCopy) and the results surprised me. I will designate the Buffer.BlockCopy as BC and looping as L. For 10x10 matrix BC = 00:00:00.0000017 and L = 00:00:00.0000030. For 100x100 matrix BC = 00:00:00.0000293 and L = 00:00:00.0000710. Finally, for 1000x1000 matrix BC = 00:00:00.0065340 and L = 00:00:00.0138396. So the Buffer.Block copy seems to outperform looping even for small matrices. I ran this on a Win 7 Ultimate (64) machine.

What about?

       double[] X = new double[]{ 1.0, 2.0, 3.0, 4.0, 5.0 };

        var lbound = X.GetLowerBound(0);
        var ubound = X.GetUpperBound(0);

       double[,] Y = new double[ubound + 1, ubound + 1];

       for (var i = lbound; i <= ubound; i++)
       {
           for (var j = lbound ; j <= ubound ; j++)
           {
               Y[i, j] = (i + j) > ubound ? 0.0 : X[i +j];
           }  
       }

Edit

This works:

 for (int targetRow = 0; targetRow <= ubound; targetRow++)
  {
    Buffer.BlockCopy
    (
        X,                                        // 1D source array
        targetRow * sizeof(double),               // source array offset
        Y,                                        // 2D target (destination) array
        (targetRow * X.Length) * sizeof(double),  // target array offset
        (X.Length - targetRow) * sizeof(double)  // count
    );
}


for (var i = 0; i <= ubound; i++)
{
    for (var j = 0; j <= ubound; j++)
    {
        Console.Write(Y[i, j] + " ");
    }
    Console.WriteLine();
}

Console.ReadKey();

阵列偏移


2nd Edit

To deal with your other requirement of changing 2nd dimension of the destination array, you need to change some of the BlockCopy parameters targetArrayOffset and count , you can map them to the dimension of the destination array as below.

        double[] X = new double[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 };

        var lbound = X.GetLowerBound(0);
        var ubound = X.GetUpperBound(0);

       double[,] Y = new double[X.Length, 3];

        int yLen = Y.GetUpperBound(1) + 1;

for (int targetRow = 0; targetRow <= ubound; targetRow++)
{
    Buffer.BlockCopy
    (
        X,                                      // 1D source array
        (targetRow * sizeof(double)),             // source array offset
        Y,                                        // 2D target (destination) array
        ((targetRow * yLen) * sizeof(double)),// target array offset
        ((X.Length - targetRow) > yLen ? yLen : (X.Length - targetRow))  * sizeof(double)  // count
    );
}

output:

ScreenPrint

Assuming x is of type double[] , use:

var y = new double[x.Length, x.Length];
for (int row = 0; row < x.Length; ++row)
{
  for (int col = 0; col < x.Length - row; ++col)
  {
    y[row, col] = x[col - row];
  }
}

or similar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM