Here's the code:
public class RhombMap
{
private Vector3 size;
private Rhomb[][][] map;
public RhombMap( int sizeX, int sizeY, int sizeZ )
{
size = new Vector3 (sizeX, sizeY, sizeZ);
Rhomb[][][] map = new Rhomb[sizeX] [sizeY] [sizeZ];
}
}
Which is annoyingly giving me the error:
Assets/Scripts/MapController.cs(186,46): error CS0021: Cannot apply indexing
with [] to an expression of type `Rhomb'
I'm not trying to index it, I'm trying to initialise an array of it, using exactly the same syntax as in Microsoft's own tutorial.
Can anyone spot what is, hopefully, a glaring error?
There's a difference between 3d array which you can initialize in one go:
Rhomb[,,] map = new Rhomb[sizeX, sizeY, sizeZ];
and jagged array (array of array of array) where you have to create each of the inner arrays:
Rhomb[][][] map = Enumerable
.Range(0, SizeX)
.Select(x => Enumerable
.Range(0, SizeY)
.Select(y => new Rhomb[SizeZ])
.ToArray())
.ToArray();
Please, notice, that you've redeclared map as a local variable within RhombMap constructor
Edit: diffrence between 2d array (let me not put 3d) and jagged one illustrated:
// 2d: always rectangle (2x3 in this case - 2 rows each of 3 items)
// that's why when been initializing wants just width and height
int[,] arr2d = new int[,]
{{1, 2, 3}
{4, 5, 6}};
// width and hight
int[,] arr2d_empty = new int[2, 3];
// jagged: all rows (subarrays) are of arbitrary lengths
// that's why when been initializing wants all rows been initialized individually
int[][] jagged = new int[][] {
new int[] {1, 2, 3, 4}, // 4 items
new int[] {5}, // 1 item
new int[] {6, 7, 8}, // 3 items
};
// each line (subarray) must be specified
int[][] jagged_empty = new int[][] {
new int[4],
new int[1],
new int[3],
};
private Rhomb[][][] map;
...
Rhomb[][][] map = ...
You've declared a new variable with the same name.
Additionally, as you've declared an array-of-arrays, you can't one-line create a new instance. You can either use one of Dmitry's solutions or do it this way:
map = new Rhomb[sizeX][][];
for(int x = 0; x < sizeX; x++) {
map[x] = new Rhomb[sizeY][];
for(int y = 0; y < sizeY; y++) {
map[x][y] = new Rhomb[sizeZ];
}
}
I still think Dmitry's solution of declaring your array as Rhomb[,,] would be best, though.
Related
I want to create array 10 * 10 * 10 in C# like int[][][] (not int[,,]).
I can write code:
int[][][] count = new int[10][][];
for (int i = 0; i < 10; i++)
{
count[i] = new int[10][];
for (int j = 0; j < 10; j++)
count[i][j] = new int[10];
}
but I am looking for a more beautiful way for it. May be something like that:
int[][][] count = new int[10][10][10];
int[][][] my3DArray = CreateJaggedArray<int[][][]>(1, 2, 3);
using
static T CreateJaggedArray<T>(params int[] lengths)
{
return (T)InitializeJaggedArray(typeof(T).GetElementType(), 0, lengths);
}
static object InitializeJaggedArray(Type type, int index, int[] lengths)
{
Array array = Array.CreateInstance(type, lengths[index]);
Type elementType = type.GetElementType();
if (elementType != null)
{
for (int i = 0; i < lengths[index]; i++)
{
array.SetValue(
InitializeJaggedArray(elementType, index + 1, lengths), i);
}
}
return array;
}
You could try this:
int[][][] data =
{
new[]
{
new[] {1,2,3}
},
new[]
{
new[] {1,2,3}
}
};
Or with no explicit values:
int[][][] data =
{
new[]
{
Enumerable.Range(1, 100).ToArray()
},
new[]
{
Enumerable.Range(2, 100).ToArray()
}
};
There is no built in way to create an array and create all elements in it, so it's not going to be even close to how simple you would want it to be. It's going to be as much work as it really is.
You can make a method for creating an array and all objects in it:
public static T[] CreateArray<T>(int cnt, Func<T> itemCreator) {
T[] result = new T[cnt];
for (int i = 0; i < result.Length; i++) {
result[i] = itemCreator();
}
return result;
}
Then you can use that to create a three level jagged array:
int[][][] count = CreateArray<int[][]>(10, () => CreateArray<int[]>(10, () => new int[10]));
With a little help from Linq
int[][][] count = new int[10].Select(x => new int[10].Select(x => new int[10]).ToArray()).ToArray();
It sure isn't pretty and probably not fast but it's a one-liner.
There is no 'more elegant' way than writing the 2 for-loops. That is why they are called 'jagged', the sizes of each sub-array can vary.
But that leaves the question: why not use the [,,] version?
int[][][] count = Array.ConvertAll(new bool[10], x =>
Array.ConvertAll(new bool[10], y => new int[10]));
A three dimensional array sounds like a good case for creating your own Class. Being object oriented can be beautiful.
You could use a dataset with identical datatables. That could behave like a 3D object (xyz = row, column, table)... But you're going to end up with something big no matter what you do; you still have to account for 1000 items.
Why don't you try this?
int[,,] count = new int[10, 10, 10]; // Multi-dimentional array.
Any problem you see with this kind of representation??
Consider I have an Array,
int[] i = {1,2,3,4,5};
Here I have assigned values for it. But in my problem I get these values only at runtime.
How can I assign them to an array.
For example:
I get the max size of array from user and the values to them now how do I assign them to the array int [].
Or can I use anyother data types like ArrayList etc which I can cast to Int[] at the end?
Well, the easiest is to use List<T>:
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
int[] arr = list.ToArray();
Otherwise, you need to allocate an array of suitable size, and set via the indexer.
int[] arr = new int[5];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
This second approach is not useful if you can't predict the size of the array, as it is expensive to reallocate the array every time you add an item; a List<T> uses a doubling strategy to minimize the reallocations required.
You mean?
int[] array = { 1, 2, 3, 4, 5 };
array = new int[] { 1, 3, 5, 7, 9 };
array = new int[] { 100, 53, 25, 787, 39 };
array = new int[] { 100, 53, 25, 787, 39, 500 };
Use List<int> and then call ToArray() on it at the end to create an array. But do you really need an array? It's generally easier to work with the other collection types. As Eric Lippert wrote, "arrays considered somewhat harmful".
You can do it explicitly though, like this:
using System;
public class Test
{
static void Main()
{
int size = ReadInt32FromConsole("Please enter array size");
int[] array = new int[size];
for (int i=0; i < size; i++)
{
array[i] = ReadInt32FromConsole("Please enter element " + i);
}
Console.WriteLine("Finished:");
foreach (int i in array)
{
Console.WriteLine(i);
}
}
static int ReadInt32FromConsole(string message)
{
Console.Write(message);
Console.Write(": ");
string line = Console.ReadLine();
// Include error checking in real code!
return int.Parse(line);
}
}
If you want an array, whose size varies during the execution, then you should use another data structure. A generic List will do. Then, you can dynamically add elements to it.
Edit: Marc posted his answer while I was writing mine. This was exactly what I meant.
You could just use the below line instead of calling a separate function:
using System;
public class Test
{
static void Main()
{
Console.WriteLine("Please enter array size");
int size = Convert.ToInt32(Console.ReadLine());
int[] array = new int[size];
for (int i=0; i < size; i++)
{
Console.WriteLine("Please enter element " + i);
array[i] = Convert.ToInt32(Console.ReadLine());
}
Console.WriteLine("Finished:");
foreach (int i in array)
{
Console.WriteLine(i);
}
}
I'm writing a program in c# that associates an array of 12 elements to a triplet of values. I would like to store my data in a matrix of dimension [n,m,p], but where each element is actually an array. The real world application is saving the output of 12 sensors for each point in a 3D cartesian space.
I tried something like this:
int[][,,] foo = new int[12][,,];
But this, if I'm right, creates an array of 12 matrices 3x3, while i want a NxMxP matrix of 12 elements arrays.
If I try to specify the matrix dimensions like this:
int[][,,] foo = new int[12][N,M,P];
I get error CS0178 (Invalid rank specifier: expected ',' or ']') and CS1586 (Array creation must have array size or array initializer).
I'm still learning c#, please excuse me for the trivial question, but I can't wrap my head around this. I'm using visual studio 2015.
If you want to create 12 instances of [N, M, P] matrices organized as an array (please, notice that int[][,,] is array of matrices, not matrix of arrays):
int[][,,] foo = Enumerable
.Range(0, 12)
.Select(_ => new int[N, M, P])
.ToArray();
Or
int[][,,] foo = Enumerable
.Repeat(new int[N, M, P], 12)
.ToArray();
If you prefer loop
// please, notice the different declaration:
int[][,,] foo = new int[12];
for (int i = 0; i < foo.Length; ++i)
foo[i] = new int[N, M, P];
Edit: if you want [N, M, P] matrix of arrays (see comments):
I'm trying to get NMP instances of 12-elements arrays, addressable by
the n,m,p indices
// please, notice the different declaration: matrix of arrays
int[,,][] foo = new int[N, M, P][];
for (int i = 0; i < foo.GetLength(0); ++i)
for (int j = 0; j < foo.GetLength(1); ++j)
for (int k = 0; k < foo.GetLength(2); ++k)
foo[i, j, k] = new int[12];
Try using a 4 dimensional array.
int[,,,] foo = new int[N,M,P, 12];
int[][,,] foo
You are creating an array of 3-D arrays (of int). If you want to initialize that array then you would have to do this:
int[][,,] foo = new int[12][,,];
And then loop through foo and for each cell initialize the 3-D array:
foo[i] = new int[M,N,P];
You can use some LINQ to make it a one-liner (see Dmitry's answer), but it basically amounts to the same thing.
Multi-dimensional arrays in C# are kind of a pain to work with.
I don't know if it will help you (maybe you need only arrays) but you can try to create simple Point3D class. This will improve readibility and, I think, maintanance.
public class Point3D
{
int X { get; set; }
int Y { get; set; }
int Z { get; set; }
public Point3D(int x, int y, int z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
}
And then:
Point3D[] arrayOfPoints = new Point3D[12];
arrayOfPoints[0] = new Point3D(0, 2, 4);
How can we initialize a multidimensional array without pre-existing values? Only the third one is correct, but it works with pre-existing values. I would like my multidimensional array to contain 10 or 20 values, and add them later on with numbers[y][x] :
int[][] numbers = new int[10][];
//List<int[]> numbers = new List<int[]>();
//int[10][]{ new int[]{}};
//correct : { new int[] {1, 2}, new int[] {3, 4, 5} };
numbers[0][0] = 58;
Would you know how to do this? (I don't know if [,] is the same as [][] by the way)
Thanks
Would you know how to do this? (I don't know if [,] is the same as [][] by the way)
there are not the some as int[][] test = new int[10][]; is called a jagged array (array of arrays) and int[,] is a fixed array
just declare your array as the following
int[,] test = new int[10,30];
test[0,1] = 10;
test[1,2] = 20;
You can try initiating values this way, it is one way to create jagged-array
int[][] test = new int[10][];
test[0] = new int[20];
test[1] = new int[30];
test[2] = new[] { 3, 4, 5 };
test[0][1] = 10;
test[1][2] = 20;
I'm trying to create a multidimensional array to contain arrays of cartesian coordinates (x,y) in a multidimensional array of [X,Y] width and height.
This is where I've gotten to so far; I've become hopelessly confused...
int[][][] grid = new int[width][][];
for (int x = 0; x < width; x++)
{
grid[x] = new int[height][];
for (int y = 0; y < height; y++)
{
grid[y] = new int[2][];
}
}
foreach (int[][] coordinate in grid)
{
//
}
For example, I'd like a 3 x 4 grid to be represented by an array as such:
{1, 1}, {2, 1}, {3, 1}
{1, 2}, {2, 2}, {3, 2}
{1, 3}, {2, 3}, {3, 3}
{1, 4}, {2, 4}, {3, 4}
etc...
I've scoured the web for a solution in C# (I'm a relative newcomer to OO, unfamiliar with C, C++ etc.) but have so far drawn a blank.
Am I on the right track in the approach I've taken with the creation of the array?
Can anyone offer some tips on how to populate the array with the coordinates, using loops if possible?
Instead of having a multidimensional array, you could create a class to hold the coordinates (and other stuff related to each tile).
For example, it could look like this :
public class Tile
{
public int X {get; set;}
public int Y {get; set;}
public bool HasMine {get; set;}
//Etc.
}
So instead of having a multidimensional array, you could use a simple List<Tile> to hold all your tiles. All you have to do to populate that list is create a new Tile instance for every tiles, like this :
List<Tile> tiles = new List<Tile>();
for(int i = 0; i < NB_HORIZONTAL_TILES; i++)
for (int j = 0; j < NB_VERTICAL_TILES; j++)
tiles.Add(new Tile { X = i; Y = j });
To iterate over them, you can simply use a foreach statement or some LINQ. That would be a more OO way to solve the problem.
assuming width and height are integers with your width and height:
int[,] grid = new int[width,height];
Will create a width x height array filled with zeros (because that's the default value for an integer).
The coordinates of the array are the indexes into the array, so you don't need to populate it for that. All you need to do is store whatever data you want to store at which ever location you want to populate:
grid[2,1] = 5; // the cell at {2,1} now contains the number 5