Related
I recently discovered that two ways to declare array in C#, those are:
int[,] array = new int[4, 2];
int[] test = { 4, 2 };
Could anyone please describe the difference between those two statements?
int[,] array = new int[4, 2];
creates array with 8 elements having the default value of 0 and 2 dimensions
int[] test = { 4, 2 };
creates array with 2 elements(4 and 2) and 1 dimension
I'm having trouble while attempting to extract a row from my array. This is my code :
using System;
namespace C_sharp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!. This is the one !");
dynamic[] res = new Object[3];
res[0] = new int[2,2]{{3,2},{16,9}};
res[1] = new int[2,2]{{4,7},{6,29}};
res[2] = new int[2,2]{{30,29},{5,49}};
//dynamic resultat = res[0][0];
}
}
}
As you can see, at the end of my program, the contents of my local variable res looks like this :
[0] [dynamic]:{int[2, 2]}
[0, 0] [int]:3
[0, 1] [int]:2
[1, 0] [int]:16
[1, 1] [int]:9
[1] [dynamic]:{int[2, 2]}
[0, 0] [int]:4
[0, 1] [int]:7
[1, 0] [int]:6
[1, 1] [int]:29
[2] [dynamic]:{int[2, 2]}
[0, 0] [int]:30
[0, 1] [int]:29
[1, 0] [int]:5
[1, 1] [int]:49
Now, I want to put only the first row of res[0] in my variable resultat in order to get a 1D array. So, at the end of the process, resultat should be equal to :
[0] [int]:3
[1] [int]:2
I've already tried res[0][0,] and res[0][0:]. None of them worked. Any help ?
You can flatten 2d array using .Cast<int>() and then take first row using .Take(2):
const int arraySize = 2;
var resultat = (res[0] as int[,]).Cast<int>().Take(arraySize).ToArray();
In general case for an arbitrary row index you can use .Skip(arraySize * rowIndex)
If it is too slow for you, you may try Buffer.BlockCopy:
const int rowSize = 2;
const int intSize = 4;
int[] resultat = new int[rowSize];
Buffer.BlockCopy(res[0], 0, resultat, 0, intSize * rowSize);
In general case it would be
const int intSize = 4; // Size of integer type in bytes
int[,] matrix = res[0];
int rowSize = matrix.GetLength(1); // Get size of second 2d-array dimension
int rowIndex = 0; // Index of a row you want to extract
int[] resultat = new int[rowSize];
Buffer.BlockCopy(res[0], // Copy source
rowSize * intSize * rowIndex, // Source offset in bytes
resultat, // Copy destination
0, // Destination offset
intSize * rowSize); // The number of bytes to copy
Buffer.BlockCopy documentation
As far as I know, a 2-D array is laid out in memory exactly like a 1-D array, it just uses different indexing. So given that, it seems like there must be some way (probably unsafe) in C# to convert a 1-D array to a 2-D array without actually copying elements, assuming you want the elements from the 1-D array to translate to the 2-D array in a row-first manner. I did figure out how to accomplish this with a single copy command, but it still seems like more processing than is necessary:
int[] onedim = new int[] { 5, 3, 6, 2, 1, 5 };
int[,] twodim = new int[2, 3];
GCHandle pinnedArray = GCHandle.Alloc(twodim, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
Marshal.Copy(onedim, 0, pointer, onedim.Length);
pinnedArray.Free();
Is there some way that I could tell C#, treat this 1-D array as a 2-D array with these dimensions instead? Unsafe code is fine. If not, is this a limitation of the language or is there some fundamental problem I am missing?
One way would be to define a class that accesses the underlying 1D array
public class Array2D<T>
{
private readonly T[] _data;
private readonly Int32 _dimX;
private readonly Int32 _dimY;
public Array2D(T[] data, Int32 dimX, Int32 dimY)
{
_data = data;
_dimX = dimX;
_dimY = dimY;
}
public T this [Int32 x, Int32 y]
{
get { return _data[x * _dimY + y]; }
set { _data[x * _dimY + y] = value; }
}
}
var array = new[] { 1, 2, 3, 4, 5, 6 };
var array2d = new Array2D<Int32>(array, 2, 3);
Assert.AreEqual(array2d[0, 0], array[0]);
Assert.AreEqual(array2d[0, 1], array[1]);
Assert.AreEqual(array2d[0, 2], array[2]);
Assert.AreEqual(array2d[1, 0], array[3]);
Assert.AreEqual(array2d[1, 1], array[4]);
Assert.AreEqual(array2d[1, 2], array[5]);
My indexing might be backwards, however this wold behave like a 2D array while maintaining the 1D array reference.
edit: Indexing was backwards, fixed it.
You could try to use the Buffer.BlockCopy method instead:
Buffer.BlockCopy(onedim, 0, twodim, 0, onedim.Length * sizeof(int));
It accepts multidimensional arrays as well.
Use Marshal.PtrToStructure.
I couldn't figure out how to do it without wrapping the 2d array in structure, but the following works without a copy.
struct array2d
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
int[,] data;
};
static void Main(string[] args)
{
int[] onedim = new int[] { 5, 3, 6, 2, 1, 5 };
array2d twoDim;
unsafe
{
fixed (int* p = onedim)
{
twoDim = Marshal.PtrToStructure<array2d>(new IntPtr(p));
}
}
}
I am new to Unity3D and c#. I am tinkering with storing some grid positions within a 2d array however I've run into
the array index is out of range
error and I don't know why:
public int[,] myArray;
myArray = new int[,]{
{0,375},
{75,300},
{150,225},
{225,150},
{300,75},
{375,0}
};
Debug.Log(myArray[1,4]); // array index is out of range... why? I expected to get 75.
Here are some other resources I was looking at for help:
http://wiki.unity3d.com/index.php/Choosing_the_right_collection_type
https://msdn.microsoft.com/en-us/library/2yd9wwz4.aspx
You have a 2D array which is 6x2 - not one which is 2x6. Each "subarray" you're specifying in the initialization is one "row", if you think of accessing the array by array[row, column].
So for example, myArray[0, 1] is 375 - the second element of the first "row", which is { 0, 375 }.
Basically, you need to pivot either your array initialization, or your array access. So if you really want a 2x6 array, you'd need:
myArray = new int[,] {
{ 0, 75, 150, 225, 300, 375 },
{ 375, 300, 225, 150, 75, 0 }
};
... or you could keep the existing initialization, and access myArray[4, 1].
The C# specification explains it like this:
For a multi-dimensional array, the array initializer must have as many levels of nesting as there are dimensions in the array. The outermost nesting level corresponds to the leftmost dimension and the innermost nesting level corresponds to the rightmost dimension. The length of each dimension of the array is determined by the number of elements at the corresponding nesting level in the array initializer. For each nested array initializer, the number of elements must be the same as the other array initializers at the same level. The example:
int[,] b = {{0, 1}, {2, 3}, {4, 5}, {6, 7}, {8, 9}};
creates a two-dimensional array with a length of five for the leftmost dimension and a length of two for the rightmost dimension:
int[,] b = new int[5, 2];
and then initializes the array instance with the following values:
b[0, 0] = 0; b[0, 1] = 1;
b[1, 0] = 2; b[1, 1] = 3;
b[2, 0] = 4; b[2, 1] = 5;
b[3, 0] = 6; b[3, 1] = 7;
b[4, 0] = 8; b[4, 1] = 9;
I am just trying out a source code.
This source code has the following line:
double[][] inputs = sourceMatrix.Submatrix(null, 0, 1).ToArray();
Originally, this "inputs" is filled using a matrix, but I am still too inexperienced to use this matrix. I would first like to test it with some hand-coded values.
Could anybody please tell me how to populate double[][] with some values?
I am not really experienced with C# yet. I guess that [][] means a threedimensional array.
In VB6 I would simply say
Redim inputs(2,2)
and then:
inputs(0,0) = 64
inputs(0,1) = 92
inputs(0,2) = 33
inputs(1,0) = 4
inputs(1,1) = 84
inputs(1,2) = 449
etc...
But I guess it is not that easy in C#.
If anybody could help, I would be really glad.
Thank you.
a double[][] is a jagged array - it is an array of arrays. To fill that you would fill the outer array with a set of double[] arrays. However, I expect you want a rectangular array: double[,], for example new double[3,2]. There is a short-hand for initializing such arrays:
double[,] data = new double[2, 3] { { 64, 92, 33 }, { 4, 84, 449 } };
double val = data[1, 2]; // 449.0
To keep it very simple:
double[][] inputs = new double[3][];
inputs[0] = new double[3];
inputs[1] = new double[3];
inputs[2] = new double[3];
inputs[0][0] = 1;
inputs[0][1] = 2;
inputs[0][2] = 3;
inputs[1][0] = 4;
inputs[1][1] = 5;
inputs[1][2] = 6;
inputs[2][0] = 7;
inputs[2][1] = 8;
inputs[2][2] = 9;
You have an array of arrays. So you should initialize them like this:
double[][] inputs = new double[][]
{
new double[] { 1, 2, 3 },
new double[] { 4, 5, 6 },
new double[] { 7, 8, 9 }
};
If you had a two dimentional array (inputs[,]) then it would be:
double[,] inputs = new double[,]
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
But as Jon Skeet said, reading about arrays is the first thing you should do.
Take a look at using double[,] this is what you need Arrays
double[][] is a jagged array.
You probably mean double[,] which is two dimensional array.
Initializing a two dimensional array:
double[,] matrix = new double[3,2] = {{1,2} {3,4}, {4,5}}
You already have examples for initializing jagged arrays, from the other answers.
The difference between jagged and true multidimensional arrays in practice is jagged arrays are arrays of arrays so it is possible for them not to be rectangular, i.e. a matrix, hence jagged:
double[][] jagged = new double[2]
{
new double[4],
new double[2]
};
The way they are layed out in memory is also different. A multidimensional array is a single reference to a contiguous memory space. Jagged arrays are true array of arrays.
Read more about it here