C# Matrix of arrays - c#

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);

Related

How to store object values in a jagged array in C# [duplicate]

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??

Finding the next available position in an array

I have a two-dimensions array of a fixed size of 50 elements. I need to ask the user for some values and insert them into the array. The problem is "How do I make sure I'm not overwriting anything that's in there?"
There will already be some content in the array when I start the program, but I don't know how much. How can I find the next available ID in the array, to insert my content there without overwriting anything that could be already in there?
I tried using array.GetUpperBound and array.GetLength, however they return fixed values no matter how many elements are already in the array.
I have to use an array, I can't use lists or anything like that.
What can I do to find out the next "free" position in my array?
Thank you very much for helping.
Well if you are using Array, all your values will contain a default value.For example if you have an two-dimensional int array like this:
var arr = new int[2, 3];
arr[1,2] will be equal to 0 which is default value for int.Anyway you can define an extension method to find available position for a two-dimensional array like this:
public static class MyExtensions
{
public static void FindAvailablePosition<T>(this T[,] source, out int x, out int y)
{
for (int i = 0; i < source.GetLength(0); i++)
{
for (int j = 0; j < source.GetLength(1); j++)
{
if (source[i, j].Equals(default(T)))
{
x = i;
y = j;
return;
}
}
}
x = -1;
y = -1;
}
}
And you can use it like this:
var arr = new int[2, 3];
arr[0, 0] = 12; // for example
int x, y;
arr.FindAvailablePosition(out x,out y);
// now x = 0, y = 1

Creating a big array C#

I'm very, very new to C# and would like to ask a maybe very stupid question, the first language I learned was Java, in which I could do this:
int[][] array = new int[1600][900];
array[600][400] = 10;
for(int x = 0; x < 1600; x++)
{
for(int y = 0; y < 900; y++)
{
int something = colour[x][y];
}
}
Now I've searched the web for quite a while, but I've got no idea about how to do this in C#
EDIT:
Thanks for the help everyone, it's been usefull :)
Just use a comma :
int[,] array = new int[1600,900];
array[600,400] = 10;
//...
You can do it in a very similar way in C#:
int[,] array = new int[1600,900];
array[600,400] = 10;
for(int x = 0; x < 1600; x++)
{
for(int y = 0; y < 900; y++)
{
int something = colour[x,y];
}
}
I'm not sure if I understand what's the purpose of the code in the double for cycle. I suppose those three pieces of code don't have anything in common.
int [,] array = new int[1600,900];
To add some color to the answers:
In .NET, an int[][] is a jagged array, or an array of arrays. While this may be a perfectly good structure for you to use, it has the addded overhead that each array must be initialized individually. So your initialization would be:
int[][] array = new int[1600][];
for(int i=0;i<array.Length;i++)
array[i] = new int[900];
now you can access an individual value by using
array[600][400] = 10;
One benefit of using jagged arrays is that the "interior" array can be different sizes. If you don;t need that flexibility than using a rectangular ([,]) array may be a better option for you.

How to create array of 100 new objects?

I'm trying something like that:
class point
{
public int x;
public int y;
}
point[] array = new point[100];
array[0].x = 5;
and here's the error:
Object reference not set to an instance of an object. (# the last line)
whats wrong? :P
It only creates the array, but all elements are initialized with null.
You need a loop or something similar to create instances of your class.
(foreach loops dont work in this case)
Example:
point[] array = new point[100];
for(int i = 0; i < 100; ++i)
{
array[i] = new point();
}
array[0].x = 5;
When you do
point[] array = new point[100];
you create an array, not 100 objects. Elements of the array are null. At that point you have to create each element:
array[0] = new point();
array[0].x = 5;
You can change class point to struct point in that case new point[500] will create an array of points initialized to 0,0 (rather than array of null's).
As the other answers explain, you need to initialize the objects at each array location. You can use a method such as the following to create pre-initialized arrays
T[] CreateInitializedArray<T>(int size) where T : new()
{
var arr = new T[size];
for (int i = 0; i < size; i++)
arr[i] = new T();
return arr;
}
If your class doesn't have a parameterless constructor you could use something like:
T[] CreateInitializedArray<T>(int size, Func<T> factory)
{
var arr = new T[size];
for (int i = 0; i < size; i++)
arr[i] = factory();
return arr;
}
LINQ versions for both methods are trivial, but slightly less efficient I believe
int[] asd = new int[99];
for (int i = 0; i < 100; i++)
asd[i] = i;
Something like that?
Sometimes LINQ comes in handy. It may provide some extra readability and reduce boilerplate and repetition. The downside is that extra allocations are required: enumerators are created and ToArray does not know the array size beforehand, so it might need to reallocate the internal buffer several times. Use only in code whose maintainability is much more critical than its performance.
using System.Linq;
const int pointsCount = 100;
point[] array = Enumerable.Range(0, pointsCount)
.Select(_ => new point())
.ToArray()

Getting a double[] row array of a double[,] rectangular array

Suppose you have an array like:
double[,] rectArray = new double[10,3];
Now you want the fouth row as a double[] array of 3 elements without doing:
double[] fourthRow = new double[]{rectArray[3,0],
rectArray[3,1],
rectArray[3,2]};
Is it possible someway? Even using a Marshal.Something approach?
Thanks!
You can use Buffer.BlockCopy method:
const int d1 = 10;
const int d2 = 3;
const int doubleSize = 8;
double[,] rectArray = new double[d1, d2];
double[] target = new double[d2];
int rowToGet = 3;
Buffer.BlockCopy(rectArray, doubleSize * d2 * rowToGet, target, 0, doubleSize * d2);
LINQ to the rescue:
var s = rectArray.Cast<double>().Skip(9).Take(3).ToArray();
Explanation: Casting a multi-dimensional array flattens it to a single-dimensional array. After that all we need to do is skip to the element we want (the 4th element in the 2-D array resolves to Skip(9)...) and take 3 elements from it).
Why not make a generic extension method?
public static T[] GetRow<T>(this T[,] input2DArray, int row) where T : IComparable
{
var width = input2DArray.GetLength(0);
var height = input2DArray.GetLength(1);
if (row >= height)
throw new IndexOutOfRangeException("Row Index Out of Range");
// Ensures the row requested is within the range of the 2-d array
var returnRow = new T[width];
for(var i = 0; i < width; i++)
returnRow[i] = input2DArray[i, row];
return returnRow;
}
Like this all you have to code is:
array2D = new double[,];
// ... fill array here
var row = array2D.GetRow(4) // Implies getting 5th row of the 2-D Array
This is useful if you're trying to chain methods after obtaining a row and could be helpful with LINQ commands as well.
You probably want to use a jagged array. That is not an array of 10 by 3 but instead an array of arrays.
Something like :
double[][] rectArray;
....
double [] rowArray = rectArray[3];
There are lots of places to learn more about jagged arrays. For example Dynamically created jagged rectangular array
If you must use a rectangular array and just want to simplify the syntax, you can use a method to get the row like so:
double[] fourthRow = GetRow(rectArray, 3);
public static T[] GetRow<T>(T[,] matrix, int row)
{
var columns = matrix.GetLength(1);
var array = new T[columns];
for (int i = 0; i < columns; ++i)
array[i] = matrix[row, i];
return array;
}
Although this is an old thread, an addition to Joseph Sturtevants answer may be useful. His function crashes in case the matrix's first column is not zero, but another integer.
This is e.g. always the case in case of retrieving data from Excel, like
object[,] objects = null;
Excel.Range range = worksheet.get_Range("A1", "C5");
objects = range.Cells.Value; //columns start at 1, not at 0
The GetRow function could be modified like this:
public static T[] GetRow<T>(T[,] matrix, int row, int firstColumn)
{
var columns = matrix.GetLength(1);
var array = new T[columns];
for (int i = firstColumn; i < firstColumn + columns; ++i)
array[i-firstColumn] = matrix[row, i];
return array;
}

Categories