This seems extremely simple, yet I can't seem to find applicable documentation anywhere. In C#, how do you create a 'double[,]'? Specifically, the data I'm trying to represent is something like this:
[0,0] = 0
[0,1] = 1
[1,0] = 1
[1,1] = 2
I have tried [[0,1],[1,2]] and the equivalent with {{}{}} and {[][]} and various other things, but cannot seem to figure out the syntax. It seems that a simple [0,1] alone is a 'double[,]' but I would like to find a way to represent the above data (more than just 2 numbers).
What am I missing? If anyone can point me to some simple documentation, that would be great.
See Array initializers:
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.
In our case:
double[,] a = { { 0, 1 }, { 1, 2 } };
A multi-dimensional double array:
Double[,] newdouble = new Double[2,2];
or
Double[,] newdouble = { { 0, 0 }, { 1, 1 } };
In order to create a two dimensional array that you can assign to, you are going to need to first allocate the correct size. In this case, you have 2 rows and 2 columns, so that will be a [2,2].
double[,] twod = new double[2,2];
Next you simply assign to it like this
twod[0,0] = 0;
twod[0,1] = 1;
twod[1,0] = 1;
twod[1,1] = 2;
And then work with it however you wish.
There is three ways to initialized your array:
double[,] twoDemn = { { 0 , 1 }, { 1 , 2 } };
or:
double[,] twoDemn = new double[,] { { 0 , 1 }, { 1 , 2 } };
or:
double[,] twoDemn = new double[2,2];
twoDemn[0,0] = 0;
twoDemn[0,1] = 1;
twoDemn[1,0] = 1;
twoDemn[1,1] = 2;
Related
Lets say I have an array of employee wages in the order of average, max, and min:
int[] wages = {0, 0, Int32.MaxValue};
The above code is initalized so that as Im finding the max I can do a comparison to 0 and anything above the existing value will beat it and replace it. So 0 works fine here. Looking at the min, if I were to set that to 0 I'd have a problem. Comparing wages (all greater than 0) and replacing the minimum with the lowest wage will be impossible because none of the wages would be below the 0 value. So Instead I've used Int32.MaxValue because It's guaranteed every wage will be below this value.
This is just one example but there are others where it would be convenient to reset and array back to its initialized contents. Is there syntax for this in c#?
EDIT: #Shannon Holsinger found an answer with:
wages = new int[] {0, 0, Int32.MaxValue};
Short answer is that there's not a built-in way of doing this. The framework doesn't automatically keep track of your array's initial state for you, just its current state, so it has no way of knowing how to re-initialize it to its original state. You could do it manually though. The exact approach to this depends on what your array was initialized to in the first place:
// Array will obviously contain {1, 2, 3}
int[] someRandomArray = { 1, 2, 3 };
// Won't compile
someRandomArray = { 1, 2, 3 };
// We can build a completely new array with the initial values
someRandomArray = new int[] { 1, 2, 3 };
// We could also write a generic extension method to restore everything to its default value
someRandomArray.ResetArray();
// Will be an array of length 3 where all values are 0 (the default value for the int type)
someRandomArray = new int[3];
The ResetArray extension method is below:
// The <T> is to make T a generic type
public static void ResetArray<T>(this T[] array)
{
for (int i = 0; i < array.Length; i++)
{
// default(T) will return the default value for whatever type T is
// For example, if T is an int, default(T) would return 0
array[i] = default(T);
}
}
I have a class piece where I define each piece shape.
myShape.Add(new piece
{
Height = 3,
Width = 2,
Name = "3x2 L TopRight",
Size = 4,
Shape = new int[][] {
new int[] { 1, 0 },
new int[] { 1, 0 },
new int[] { 1, 1 }
}
});
But I create those shape by hand, now I reading the pieces in real time, so I create something like
List<int[]> virtualRow = new List<int[]>();
virtualRow.Add(new int[] { 1, 0 });
virtualRow.Add(new int[] { 1, 0 });
virtualRow.Add(new int[] { 1, 1 });
So how can I create Shape using virtualRow ?
I try something like
Shape = new int[][] { virtualRow.ToArray() }
But say
Cannot implicitly convert type 'int[][]' to 'int[]'
virtualRow.ToArray() is already an array of array of int values. You don't need to create a new array of array of ints and add this to it.
All you need is:
Shape = virtualRow.ToArray(),
virtualRow is a List of integer arrays, so to get an array of integer arrays you simply write:
Shape = virtualRow.ToArray();
...the return type of List.ToArray() being T[] as required.
Your code is in error because it attempts to add an int[][] to Shape instead of creating Shape as an int[][].
You want to do the following:
Shape = virtualRow.ToArray();
Since virtualRow is already a list of arrays. The ToArray function creates an int[][] object for your virtualRow, and all you need to do is store it to shape. What you were trying to do was create a matrix, within which was the result of the ToArray function. This way you are just storing the result of the function which gives you what you want.
I'm new at C# and I want to create a multidimensional array like this:
(source: parks.ca.gov)
But in 8x8x4 cells.
I want to store maze cells.
{
{1,1,1,0}, {1,0,0,0}, {1,1,1,1}, {1,0,0,0}, {1,1,0,1}, {1,1,0,1}, {0,1,0,0}, {1,0,0,1},
...
{0,1,1,0}, {1,0,1,0}, {0,0,1,1}, {1,0,1,0}, {1,0,0,1}, {0,1,0,1}, {1,1,1,0}, {1,1,0,1},
}
int[,,] table = new int[8,8,4]; // is this right?
table[0,0] = {0, 0, 1, 1}; // I want to fill it this way.
I'm aware it does not explicitly answer the question, but in my opinion you're shooting yourself in the foot by working with 3D arrays. C# is an OO language, so it really helps if you think OO.
Instead of working with a multidimensional array representing cells for you 3d Maze (if it is really a 3d maze you want), why not create a List of classes named Cell, each one containing their position and other stuff you need, like :
public class Cell
{
public Cell (int x, int y, int z)
{
X = x;
Y = y;
Z = z;
}
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
public bool IsExplored { get; set; }
}
Then you can have a simple List<Cell> that you can iterate over.
You can also remove the x,y,z and create a Position class.
For walls, you can create an Enum and use bitwise operations, or store a list of Enum. Since you're a beginner, I'd suggest you the list of enums. You would have to add this Enum in the code, and this property to the Cell class :
public Enum WallPosition
{
Top,
Left,
Bottom,
Right
}
public List<WallPosition> walls { get; set;} //This goes into the Cell class
That way, every operation will be much much easier to do. For example, if you need to explore every cell at the column #3, you can do
foreach (Cell cell in yourCellList.Where(c => c.Y == 3))
{
cell.IsExplored = true;
}
Need to render every explored cell differently?
foreach (Cell cell in yourCellList.Where(c => c.IsExplored) { //Do stuff }
And so on.
No need for complicated for loops with your 3 dimensions, and a simple foreach is in my opinion far more readable than a
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
for (int k = 0; k < 4; k++)
every time you need to access your table.
The only ugly part would be to fill you list (By creating new Cell instances), but it would still be far more readable than a huge wall of { { { 0, 1, 0, 1 }, {1, 1, 1, 0} [...]
I'd also suggest that you read an introduction to OO principles.
With multidimensional arrays, you can either set them all at once (using basically the syntax you showed):
int[,,] table = {
{ { 1, 1, 1, 0 }, { 1, 0, 0, 0 } },
{ { 0, 1, 1, 0 }, { 1, 0, 1, 0 } }
};
or you can set the items one by one:
int[,,] table = new int[8,8,4];
table[0,0,0] = 0;
there is nothing in between. The best you could do is to write an extension method that would work something like this:
table.Set(0, 0, new int[] { 0, 0, 1, 1 });
As an alternative, you could use 2D array of arrays:
int[,][] table = {
{ new[] { 1, 1, 1, 0 }, new[] { 1, 0, 0, 0 } },
{ new[] { 0, 1, 1, 0 }, new[] { 1, 0, 1, 0 } }
};
or you could use almost the syntax you proposed:
int[,][] table = new int[8,8][];
table[0,0] = new[] { 0, 0, 1, 1 };
A disadvantage of this approach is that it doesn't force the inner arrays to be all the same length.
As proposed in comments, another option would be use a custom type like Cell and have a 2D array of those. Doing that makes it clearer what the array actually means, table[0,0].Left is certainly more readable than table[0,0,1].
If the wall can be there or not, you shouldn't use int values 0 and 1, you should use bool values false and true. If you want to have more states, an enum might be appropriate.
Your structure contains a lot of duplication, since bottom of a cell is the same as top of the cell below it (unless you want to have one way walls). This means the structure can get into an inconsistent state, which is often hard to debug (“The wall isn't there? But I just looked and it is there.”).
One way to avoid that would be store walls instead of cells. Instead of 8×8 cells, you would have 8×9 horizontal walls and 9×8 vertical walls. You could then have methods that would abstract this away, so you could easily look up walls of a particular cell.
An array initializer for a 3D array would look like this:
int[,,] table = {
{ {1,1,1,0}, {1,0,0,0}, ... },
{ {0,1,1,0}, {1,0,1,0}, ... },
...
};
The first line is right. The second line won't work. The closest thing is to use a 2D array of arrays:
int[,][] table = new int[8,8][];
table[0,0] = new int[] {0, 0, 1, 1};
Like #tigrou and #Pierre-Luc Pineault suggested, it would be a lot cleaner to encapsulate each cell in an object instead of a plain array.
Consider storing the data in an external file and reading it in instead of hardcoding the 256 numbers.
I am trying to initialize 2-dimensional array of integer values with -1. When I create a new array, it is automatically filled with 0.
I know I can do it with 2 for cycles, but I imagine there should be some way of doing this while the array is being build (so I don't have to go through it two times), so that instead of 0, provided value would be inserted. Is it possible?
If not during the initial building of the array, is there some other time or code saving way, or am I stuck with 2 for cycles?
Try something like this: int[,] array2D = new int[,] { { -1 }, { -1 }, { -1 }, { -1} };
or with dimension int[,] array2D = new int[4,2] { { -1,-1 }, { -1,-1 }, { -1,-1 }, {-1,-1} };
With a multidimensional array, the loops are most likely the best approach, unless the array is small enough to initialize directly in code.
If you're using a jagged array, you could initialize the first sub-array, then use Array.Copy to copy these values into each other sub-array. This will still require one iteration through the first sub array, and one loop through N-1 outer arrays, but the copy operation will be faster than the loops.
In Python, this kind of 2D array initialization is wrong:
mat = [[0] * 5] * 5 # wrong
mat = [[0] * 5] for _ in range(5)] # correct
because you are copying the reference of the inner array multiple times, and changing one of them will eventually change all.
mat[0][0] = 1
print(mat)
# 1 0 0 0 0
# 1 0 0 0 0
# 1 0 0 0 0
# 1 0 0 0 0
# 1 0 0 0 0
In C#, we have the similar issue.
var mat = Enumerable.Repeat(Enumerable.Repeat(0, 5).ToArray(), 5).ToArray();
Since array is a reference type, the outside Repeat() are actually copying the reference of the inner array.
Then if you do have the need to create and initialize multidimensional arrays without using for loops, then maybe a custom helper class will help:
static class HelperFunctions
{
public static T[][] Repeat<T>(this T[] arr, int count)
{
var res = new T[count][];
for (int i = 0; i < count; i++)
{
//arr.CopyTo(res[i], 0);
res[i] = (T[])arr.Clone();
}
return res;
}
}
Then if you want to use it:
using static HelperFunctions;
var mat = Enumerable.Repeat(0, 5).ToArray().Repeat(5);
This will do.
My following code has compile error,
Error 1 Cannot implicitly convert type 'TestArray1.Foo[,,*]' to 'TestArray1.Foo[][][]' C:\Users\lma\Documents\Visual Studio 2008\Projects\TestArray1\TestArray1\Program.cs 17 30 TestArray1
Does anyone have any ideas? Here is my whole code, I am using VSTS 2008 + Vista 64-bit.
namespace TestArray1
{
class Foo
{
}
class Program
{
static void Main(string[] args)
{
Foo[][][] foos = new Foo[1, 1, 1];
return;
}
}
}
EDIT: version 2. I have another version of code, but still has compile error. Any ideas?
Error 1 Invalid rank specifier: expected ',' or ']' C:\Users\lma\Documents\Visual Studio 2008\Projects\TestArray1\TestArray1\Program.cs 17 41 TestArray1
Error 2 Invalid rank specifier: expected ',' or ']' C:\Users\lma\Documents\Visual Studio 2008\Projects\TestArray1\TestArray1\Program.cs 17 44 TestArray1
namespace TestArray1
{
class Foo
{
}
class Program
{
static void Main(string[] args)
{
Foo[][][] foos = new Foo[1][1][1];
return;
}
}
}
EDIT: version 3. I think I want to have a jagged array. And after learning from the fellow guys. Here is my code fix, and it compile fine in VSTS 2008. What I want is a jagged array, and currently I need to have only one element. Could anyone review whether my code is correct to implement my goal please?
namespace TestArray1
{
class Foo
{
}
class Program
{
static void Main(string[] args)
{
Foo[][][] foos = new Foo[1][][];
foos[0] = new Foo[1][];
foos[0][0] = new Foo[1];
foos[0][0][0] = new Foo();
return;
}
}
}
thanks in advance,
George
Regarding version 2 of your code - unfortunately you can't specify jagged arrays in that way. Instead, you need to do:
Foo[][][] foos = new Foo[1][][];
foos[0] = new Foo[1][];
foos[0][0] = new Foo[1];
You have to populate each array separately, basically. Foo[][][] means "an array of arrays of arrays of Foo." An initialization statement like this is only capable of initializing one array at a time. With the rectangular array, you still end up with just a single (multi-dimensional) array, which is why new Foo[1,1,1] is valid.
If this is for real code by the way, I'd urge you to at least consider other design decisions. Arrays of arrays can be useful, but you can easily run into problems like this. Arrays of arrays of arrays are even nastier. There may be more readable ways of expressing what you're interested in.
Make up your mind :)
You either want:
Foo[,,] foos = new Foo[1, 1, 1];
or:
Foo[][][] foos = new Foo[1][1][1];
You are declaring a double-nested array (array of array of array) and assigning a three-dimensional array. Those two are definitely different. You can change your declaration to
Foo[,,] foos = new Foo[1,1,1]
if you want a truly three-dimensional array. Jagged arrays (the [][][] kind) are not that needed in C# as in, say, Java.
The simplest answer is to use
Foo[,,] foos = new Foo[2, 3, 4];
Which gives you a 3-dimensional array as a contiguous block of memory of 2*3*4=24 Foo's.
The alternative looks like :
Foo[][][] foos = new Foo[2][][];
for (int a = 0; a < foos.Length; a++)
{
foos[a] = new Foo[3][];
for (int b = 0; b < foos[a].Length; b++)
{
foos[a][b] = new Foo [4];
for (int c = 0; c < foos[a][b].Length; c++)
foos[a][b][c] = new Foo();
}
}
Although this jagged (= array of array) approach is a bit more work, using it is actually faster. This is caused by a shortcoming of the compiler that will always do a range check when accessing an element in the Foo[,,] case, while it is able to at least optimize for-loops that use the Length property in the Foo[][][] scenario.
Also see this question
These two different array declarations create very different things.
Let's look at simpler case:
Foo[,] twoDimensionArray = new Foo[5,5];
This array has two dimensions - you can think of it as a table. You need both axis in order to return anything:
Foo item = twoDimensionArray[2,3]
The indexes always have the same lengths - in this case 0-4.
A jagged array is actually an array of arrays:
Foo[][] jaggedArray = new Foo[5][];
jaggedArray[0] = new Foo[2];
jaggedArray[1] = new Foo[4];
...
If you only use one axis index it will return an array:
Foo[] oneRow = jaggedArray[3];
If you use both you make your selection from the sub-array:
Foo item = jaggedArray[3][2];
//would be the same as:
Foo item = oneRow[2];
Each of these sub-arrays can have a different length, or even not be populated.
Depends on whether you want them to be jagged or not:
//makes a 5 by 4 by 3 array:
string[,,] foos = new string[5,4,3];
http://msdn.microsoft.com/en-us/library/aa288453(VS.71).aspx
Oh and here is initializing values:
char[, ,] blah = new char[2, 2, 2] {
{{ '1', '2' }, { '3', '4' }},
{{ '5', '6' }, { '7', '8' }}
};
Note that this will not work:
Foo[][][] foos = new Foo[1][1][1];
Because you are using the jagged array syntax, which does not let you define the size of nested arrays. Instead use do this:
Foo[,,] foos = new Foo[1][1][1]; //1 by 1 by 1
or this
Foo[][][] foos = new Foo[1][][]; //1 array allowing two nested levels of jagged arrays
foos[0] = new Foo[1]; //for the first element, create a new array nested in it
foos[0][0] = new Foo[1]; //create a third level new array nested in it
If it means anything, for just the C# declaration:
int[,,] ary = new int[,,]
{
{ { 111, 112 }, { 121, 122 }, { 131, 132 } }
, { { 211, 212 }, { 221, 222 }, { 231, 232 } }
, { { 311, 312 }, { 321, 322 }, { 331, 332 } }
, { { 411, 412 }, { 421, 422 }, { 431, 432 } }
};
Array Initialization
int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } }
source: Multidimensional Arrays (C# Programming Guide)