Having the following:
int[,] a = new int[4, 2];
int[] b = new int[2];
how do I copy values from b into the first element of a? What's wrong with b.CopyTo(a[0])
?
Having the following:
int[,] a = new int[4, 2];
int[] b = new int[2];
how do I copy values from b into the first element of a? What's wrong with b.CopyTo(a[0])
?
You can access a
only by using 2 coordinates (so a[x,y]
) because it is defined using 2 dimensions.
Try using int[][] a
instead, if you do that then a
becomes an array containing 1-dimensional subarrays, and then you can use 1 coordinate to access a subarray.
Example code:
int[][] a = new int[4][];
a[0] = new int[2];
int[] b = new int[2];
Note that after this, when I try do to b.CopyTo(a[0])
I get a "The call is ambiguous " compilation error (in .NET 5) because there two different extension methods that both match the CopyTo
signature...
What's wrong with b.CopyTo(a[0])?
A is a two dimensional array, so you need two indices, i.e. a[0,0] = b[0]
Instead of using the built in multidimensional array I would suggest using a wrapper around a 1D array instead, with a indexer something like this:
public T this[int x, int y]
{
get => Data[y * Width + x];
set => Data[y * Width + x] = value;
}
This has the advantage of easier interoperability, since many system exposes 2D buffers of various kinds as 1D data + size. This allows copying data to be done by a block copy instead of copying element by element.
For primitives array types you can define extension methods for packing or unpacking arrays using the Buffer.BlockCopy();
static class Program
{
static void Main(string[] args)
{
int[,] A = new[,] { { 1, 2 }, { 3, 4 } };
int[] data = A.PackMarix();
int[,] B = data.UnPackMarix(2, 2);
Console.WriteLine(B);
}
public static int[,] UnPackMarix(this int[] data, int rows, int columns)
{
int[,] result = new int[rows, columns];
int bytes = Buffer.ByteLength(data);
Buffer.BlockCopy(data, 0, result, 0, bytes);
return result;
}
public static int[] PackMarix(this int[,] data)
{
int[] result = new int[data.Length];
int bytes = Buffer.ByteLength(data);
Buffer.BlockCopy(data, 0, result, 0, bytes);
return result;
}
}
For non-primitive types you have to do the copying manually
public static T[,] UnPackMarix<T>(this T[] data, int rows, int columns)
{
var result = new T[rows, columns];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
result[i, j] = data[i * columns + j];
}
}
return result;
}
public unsafe static T[] PackMarix<T>(this T[,] data)
{
var result = new T[data.Length];
int rows = data.GetLength(0);
int columns = data.GetLength(1);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
result[i * columns + j] = data[i, j];
}
}
return result;
}
This has been posted on SO before but I couldn't find the old post. Anyway, use the Microsoft High Performance toolkit. It has spans for 2D memory. With that you can do this:
int[,] a = new int[4, 2];
int[] b = { 1, 2 };
var spanB = b.AsSpan();
var spanA = a.AsSpan2D();
spanB.CopyTo(spanA.GetRowSpan(0));
foreach (var i in spanA)
Console.WriteLine(i);