Related
My problem is I want to initialize a multidimensional array declared like this:
int[][][] my3DArray;
However, the following code gives me an error on [sizeY][sizeZ] saying it expected ',' or ']'.
void Set3DArraySize(int sizeX, int sizeY, int sizeZ)
{
my3DArray = new int[sizeX][sizeY][sizeZ];
}
When i declare the array like this though:
int[,,] my3DArray;
I am able to initialize it without any problems by doing it like this:
my3DArray = new int[sizeX,sizeY,sizeZ];
But then the problem becomes that if I try to get the length of one of the arrays I can't do for example my3DArray[x,y].Length and am instead forced to pass all of the indexes together my3DArray[x,y,z].
So, is there any way I can initialize the array with it being declared as int[][][] my3DArray;? Or will I have to store the sizes of the arrays elsewhere and use it like this int[,,] my3DArray;?
You can do:
new int[][][] myArray = new int[][][]
{
new int[][]
{
new int[]
{
// Your numbers
}
}
}
myArray[0].Length
myArray[0][0].Length
myArray[0][0][0].Length
Works fine
int[][] is a jaggad array, which means that every array can be in a different size.
This is why you can initialize it that way:
int[][] arr2D= new int[3][];
arr2D[0] = new int[0];
arr2D[1] = new int[1];
arr2D[2] = new int[2];
which will create a 2d array that looks like this:
_
_ _
_ _ _
The following is an example to create 3d jaggad array (with different sizes for each dimension- 5 rows, 3 columns and 6 depth):
int[][][] arr3D = new int[5][][];
for (int col = 0; col < arr3D.Length; col++)
{
arr3D[col] = new int[3][];
for (int depth = 0; depth < arr3D[col].Length; depth++)
{
arr3D[col][depth] = new int[6];
}
}
In order to get the dimension size in jaggad array, you can simply get the lenth of the array, but keep in mind that if the array is actually jagged, you will have different sizes for different arrays. if you initialize all of the arrays in a specific dimension with the same value, than you can check either of them, it will be the same.
int[,] is a multi dimensional array that every dimension have a fixed size.
To create a multi dimensional:
int[,] arr2D = new int[3,4];
which will create a 2d array looking like this:
_ _ _ _
_ _ _ _
_ _ _ _
In multi dimensional array you can't change the length of a specific row or column.
In most cases you will probably prefer a multi dimensional array.
In order to get the size of a specific dimension in a multi dimensional array, you can use the following method:
int rows = arr22.GetLength(0); int cols = arr22.GetLength(1); int depth = arr22.GetLength(2);
The input is the dimension you want the size of.
You can't declare a jagged array in one line like this: new int[sizeX][sizeY][sizeZ]; as you really have three levels of nested arrays. You need to initialize them at each level.
This is what that would look like:
void Set3DArraySize(int sizeX, int sizeY, int sizeZ)
{
my3DArray = new int[sizeX][][];
for (var x = 0; x < sizeX; x++)
{
my3DArray[x] = new int[sizeY][];
for (var y = 0; y < sizeY; y++)
{
my3DArray[x][y] = new int[sizeZ];
}
}
}
Now, if you do want to initialize a multidimensional array, you can do this:
int[,,] z =
{
{ { 1, 2, }, { 1, 2, }, { 1, 2, }, },
{ { 1, 5, }, { 1, 5, }, { 2, 8, }, },
{ { 1, 5, }, { 1, 5, }, { 2, 8, }, },
{ { 1, 5, }, { 1, 5, }, { 2, 8, }, },
};
And then, to get the dimensions, you can do this:
Console.WriteLine(z.GetLength(0));
Console.WriteLine(z.GetLength(1));
Console.WriteLine(z.GetLength(2));
That gives me:
4
3
2
It's important to note that with a jagged array each nested array can be of different length, but with a multidimensional array then each dimension must be uniform.
For example, a jagged array could look like this:
int[][] y = new int[][]
{
new [] { 1, 2, },
new [] { 1, 2, 3, },
new [] { 1, },
};
And a multidimensional array like this:
int[,] y =
{
{ 1, 2, 3, },
{ 4, 5, 3, },
{ 1, 6, 3, },
{ 1, 7, 8, },
};
I could not do this:
//illegal!!!
int[,] y =
{
{ 1, 2, 3, },
{ 4, 5, 3, 7, },
{ 1, 6, },
{ 1, 7, 8, },
};
First,
int[][][]
is a jagged array, or an array of arrays of arrays. Where as,
int [,,]
is a multi-dimensioinal array. A single array with many dimensions.
While multi-dimensional arrays are easier to instantiate and will have fixed dimensions on every axis, historically, the CLR has been optimized for the vastly more common case of single dimensional arrays, as used in jagged arrays. For large sizes, you may experience unexpected performance issues.
You can still get the dimensions of a multi-dimensional array by using the GetLength method, and specifying the dimension you are interested in but, its a little clunky.
The number of dimensions can be retrieved from the Rank property.
You may prefer a jagged array and instantiating one axis at a time.
To instantiate jagged arrays, see this Initializing jagged arrays.
void Set3DArraySize(int sizeX, int sizeY, int sizeZ)
{
my3DArray = Enumerable.Repeat(Enumerable.Repeat(new int[sizeZ], sizeY).ToArray(),sizeX).ToArray();
}
Is it possible to use the new System.Memory Span struct with two dimensional arrays of data?
double[,] testMulti =
{
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 9.5f, 10, 11 },
{ 12, 13, 14.3f, 15 }
};
double[] testArray = { 1, 2, 3, 4 };
string testString = "Hellow world";
testMulti.AsSpan(); // Compile error
testArray.AsSpan();
testString.AsSpan();
Whilst testArray and testString have a AsSpan extension, no such extension exists for testMulti.
Is the design of Span limited to working with single dimensional arrays of data?
I've not found an obvious way of working with the testMulti array using Span.
You can create a Span with unmanaged memory. This will allow you to Slice and Dice indiscriminately.
unsafe
{
Span<T> something = new Span<T>(pointerToarray, someLength);
}
Full Demo
unsafe public static void Main(string[] args)
{
double[,] doubles = {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 9.5f, 10, 11 },
{ 12, 13, 14.3f, 15 }
};
var length = doubles.GetLength(0) * doubles.GetLength(1);
fixed (double* p = doubles)
{
var span = new Span<double>(p, length);
var slice = span.Slice(6, 5);
foreach (var item in slice)
Console.WriteLine(item);
}
}
Output
7
8
9
9.5
10
Other options would be to reallocate to a single dimension array, cop the penalty and do not Pass-Go
BlockCopy
or p/invoke memcpy directly and use unsafe and pointers
Cast<T> eg multiDimensionalArrayData.Cast<byte>().ToArray()
The first 2 will be more performant for large arrays.
You can use the new MemoryMarshal.CreateSpan and MemoryMarshal.GetArrayDataReference for this.
public static Span<T> AsSpan<T>(this Array array)
{
return MemoryMarshal.CreateSpan(ref Unsafe.As<byte, T>(ref MemoryMarshal.GetArrayDataReference(array)), array.Length);
}
dotnetfiddle
This works on all dimensions of arrays. If you want generic type inference to work, you will need separate functions for every rank (level of dimension), such as AsSpan<T>(this T[,] array) and AsSpan<T>(this T[,,] array).
As John Wu already mentioned spans are one dimensional.
You could of course implement a 2D span yourself, but Microsoft already did that for us.
Have a look into the docs here.
You can find the addressing nuget package here.
The package also provides a Memory2D.
var arr = new int[,] { {1,2,3},{2,2,3},{3,2,3} };
var spn = arr.AsSapn2D();
// Now use it similar to a normal span
// The access is of course a bit different since we are using a 2D data structure.
Console.WriteLine(spn[0..2,..]);
All spans are one-dimensional because memory is one-dimensional.
You can of course map all manner of structures onto one-dimensional memory, but the Span class won't do it for you. But you could easily write something yourself, for example:
public class Span2D<T> where T : struct
{
protected readonly Span<T> _span;
protected readonly int _width;
protected readonly int _height;
public Span2D(int height, int width)
{
T[] array = new T[_height * _width];
_span = array.AsSpan();
}
public T this[int row, int column]
{
get
{
return _span[row * _height + column];
}
set
{
_span[row * _height + column] = value;
}
}
}
The tricky part is implementing Slice(), since the semantics are sort of ambiguous for a two-dimensional structure. You can probably only slice this sort of structure by one of the dimensions, since slicing it by the other dimension would result in memory that is not contiguous.
As #saruman I don't believe it's possible.
You will need to get a new single dimension array first using techniques shown in Fast way to convert a two dimensional array to a List ( one dimensional ) or Convert 2 dimensional array, for example.
Perhaps there's more success to be had working with a jagged array instead of a multidimensional array.
double[][] testMulti =
{
new double[] { 1, 2, 3, 4 },
new double[] { 5, 6, 7, 8 },
new double[] { 9, 9.5f, 10, 11 },
new double[] { 12, 13, 14.3f, 15 }
};
Span<double[]> span = testMulti.AsSpan(2, 1);
Span<double> slice = span[0].AsSpan(1, 2);
foreach (double d in slice)
Console.WriteLine(d);
slice[0] = 10.5f;
Console.Write(string.Join(", ", testMulti[2]));
Console.ReadLine();
OUTPUT
9.5
10
9, 10.5, 10, 11
How can I add an array to another 2D array? For example
//change this
array2d = { {1,2,3}, {4,5,6} };
//to this
array2d = { {1,2,3}, {4,5,6}, {7,8,9} };
//by adding
array1d = {7,8,9};
Is there any better way other than create a new array, which is bigger than the old one, then copy the old array to the array?
I would recommend a List<List<int>> for something like this, unless you have a reason not to.
The code for it may look something like this:
List<List<int>> my2dList = new List<List<int>>()
{
new List<int>()
{
1,
2,
3
},
new List<int>()
{
4,
5,
6
},
};
my2dList.Add(new List<int>(){7,8,9});
Alternatively, if you really want to limit each column to a length of three, consider using an inner structure with an immutable size (array of size 3, etc)
It seems like you might want to use a different data structure, a list of arrays would make this much easier.
Extended version of the code snippet posted by #VP. includes the back-conversion from List(List> to Jagged Array using Linq:
// 2d array to List
List<List<int>> ar2list = new List<List<int>>()
{
new List<int>() { 1, 2, 3 },
new List<int>() { 4, 5, 6 },
};
// adding item to List
ar2list.Add(new List<int>() { 7, 8, 9 });
// List to Jagged array conversion using Linq
int[][] _arrConcat = ar2list.Select(Enumerable.ToArray).ToArray();
Finally, pertinent to this particular use-case as requested by OP, int[][] can be easily converted to int[,] with simple for loop:
array2d = new int[_arrConcat.Length, 3];
for (int i = 0; i<_arrConcat.Length; i++)
{
for (int j = 0; j < 3; j++)
{
array2d[i, j] = _arrConcat[i][j];
}
}
where array2d is the original array with added index/content.
Hope this will help. Best regards,
Currently I am doing this
public int[][] SomeMethod()
{
if (SomeCondition)
{
var result = new int[0][];
result[0] = new int[0];
return result;
}
// Other code,
}
Now in this I only want to return empty jagged array of [0][0]. Is it possible to reduce three lines to one. I want to achieve something like this
public int[][] SomeMethod()
{
if (SomeCondition)
{
return new int[0][0];
}
// Other code,
}
Is it possible?
In the general case, you can let the compiler count elements for you:
public int[][] JaggedInts()
{
return new int[][] { new[] { 1, 2, 3 }, new[] { 4, 5, 6 }, new[] { 7, 8, 9, 10 } };
}
Or if you want it very compact, use an expression body:
public int[][] JaggedInts() => new int[][] { new[] { 1, 2, 3 }, new[] { 4, 5, 6 }, new[] { 7, 8, 9, 10 } };
Since you asked for an empty jagged array, you already had it:
var result = new int[0][];
The next line in your question will throw a run-time exception, since [0] is the first element in an array, which must be 1 or or more elements in length;
result[0] = new int[0]; // thows IndexOutOfRangeException: Index was outside the bounds of the array.
Here is what I think you asked for in just one line:
public int[][] Empty() => new int[0][];
Please have a look here https://stackoverflow.com/a/1739058/586754 and below.
You will need to create some helper functions and then it becomes a one-liner.
(Also was looking for a 1-line-solution.)
by returning value of jagged array its give you some ambiguous result,if you want to return some specific value of some specific index of jagged array you can return by assigning them to variable
public static int aaa()
{
int[][] a = new int[2][] { new int[] { 1, 2 }, new int[] { 3, 4 } };
int abbb=a[0][0];
Console.WriteLine(a[0][0]);
return abbb;
}
the following code will return 1 becoz this is first element of jagged array
I have an array with elemnents in order 1,2,3,4,5 and I would need to reverse it so it will be 5,4,3,2,1.
What about the following pseudo code? Is here not an easier way
EDIT: I Am sorry I thought multidimensional array
someclass [,] temporaryArray=new someclass [ArrayLenght,ArrayLenght];
//for each dimension then
for(int I=0;I<ArrayLenghtOfDimension;I++)
{
temporaryArray[ArrayLenghtOfDimension-I]=Array[I];
}
Array=temporaryArray;
The array base class has a Reverse() extension method built in
int[] originalArray = new int[] { 1, 2, 3, 4, 5 };
int[] reversedArray = originalArray.Reverse().ToArray();
Note that the Reverse method returns IEnumerable, so you need to call ToArray() on the result.
And if you need to just iterate over the elements in the array, then all you need is
foreach (int element in originalArray.Reverse())
Console.WriteLine(element);
Oops - Reverse is on IEnumerable, not Array, so you can use that with any collection.
IEnumerable<int> IEnumerableInt = new List<int>() { 1, 2, 3 };
int[] reversedArray2 = IEnumerableInt.Reverse().ToArray();
Yes there is fast solution exists in .net
int[] values = new int[] { 1, 2, 3, 4, 5 };
Array.Reverse(values);
Your array is reversed. so you can iterate through it
foreach (int i in values)
{
Response.Write(i.ToString());
}
the above code will display
54321
It will also work for string[], char[] or other type of arrays
Event though the Array class has Reverse methods defined:
Array.Reverse(originalArray); // original array is now reversed
If all you need to do is iterate backwards over it do the following:
for(int I= ArrayLength - 1; I >= 0; I--)
{
}
This avoid re-allocating memory for the reversed array.
Array.Reverse is the best way to do this. Do you care about order of the elements at all? If so,then you can do the following.
int[] originalArray = new int[] { 10, 2, 13, 4, 5 };
int[] descOrderedArray = originalArray.OrderByDescending(i => i).ToArray();
int[] ascOrderedArray = originalArray.OrderBy(i => i).ToArray();
For a multi-dimensional array it's the same idea
int[][] multiDimArray = new int[][] { new int[] { 1, 2, 3 }, new int[] { 4, 5, 6 } };
int[][] reversedMultiArray = multiDimArray.Reverse().ToArray();
produces an array of two arrays that is: {4, 5, 6}, {1, 2, 3}