I need to make an 2d array, but c# won't let me and says that it is too big, any ideas how to make it work?
int[,] arrayName = new int[37153,18366];
The max theoretical size of an int array is 2147483647 i.e. int[] array = new int[2147483647] but the probleming you're having here is that the computer runs of out memory.
Read this for explanation and tips on how to solve this:
OutOfMemoryException on declaration of Large Array
If you are not using the complete range of the array (which is in your case 2,7GB of RAM), you could use a Dictionary.
https://msdn.microsoft.com/de-de/library/xfhwa508(v=vs.110).aspx
Alternative: Create a [][] Array. In this case you must initialize each row.
But you can access each cell easy with arrayName[row][col].
int[][] arrayName = new int[37153][];
for(int i=0; i<arrayName.Length; i++)
arrayName[i] = new int[18366];
Related
My program involves a 2-dimensional board: Square[width,height]. Each Square contains a collection of Pieces.
In the presentation layer, I want to only present the collection of Pieces in each Square and represent each Piece with its string Name. I.e. string[][width,height].
Declaring string[][,] compiles with no problem but I can't initialize the variable:
string[][,] multiArrayOfArrays; //No problemo
multiArrayOfArrays = new string[][8,8]; //Generates errors
The following errors are generated for the second line:
CS1586 Array creation must have array size or array initializer
CS0178 Invalid rank specifier: expected ',' or ']' ModChess
CS0178 Invalid rank specifier: expected ',' or ']' ModChess
I'm currently using List<string>[,] as a workaround but the errors vex me. Why can I successfully declare a string[][,] but not initialize it?
Note: Using VS Community 16.0.4, C# 7.3.
string[][,] multiArrayOfArrays; //No problemo
Here you just declare variable of specific type.
multiArrayOfArrays = new string[][8,8]; //Generates errors
And here you actually create new object of specific type. It generates errors because this is invalid syntax for multidimentional array initialization.
You need to specify size for first dimension [] and then initialize each element of that array with string[,].
Think of it as array of arrays:
string[][,] multiArrayOfArrays; //No problemo
multiArrayOfArrays = new string[5][,];//create 5 elements of string[,] array
for (int i = 0; i < multiArrayOfArrays.Length; ++i)
{
multiArrayOfArrays[i] = new string[8,8];//actually fill elements with string[8,8]
}
or
string[][,] multiArrayOfArrays; //No problemo
multiArrayOfArrays = new string[][,]
{
new string[8,8],
new string[8,8],
new string[8,8],
};
Probably you want a string[,][] a.
string[,][] a = new string[3, 4][];
a[0, 0] = new string[10];
a[0, 1] = new string[4];
a[1, 0] = new string[6];
string s = a[0, 0][2];
You have a special case of a jagged array, where the first array is 2-dimensional. It contains one-dimensional arrays of different sizes as elements.
The ordering of the array brackets might seem wrong, as the element type is usually on the left side of the brackets; however, if you think about on how you want to access elements, then it makes sense. First, you want to specify the 2 coordinates of the 2-dimensional board, then the single index of the pieces collection.
According to Jagged Arrays (C# Programming Guide), int[][,] jaggedArray4 = new int[3][,] "... is a declaration and initialization of a single-dimensional jagged array that contains three two-dimensional array elements of different sizes."
The original problem is that I am reading big chunks of binary data from a tool that is being developed.
My goal is to read data and parse it to a human readable text such as a .csv file, so I have to flatten
that data.
The data is in form of samples of a multidimensional array of floats, longs or ints or whatever. And
because the tool is under development the size and dimensions of the array may differ from an hour to hour!
(e.g. right now I may have samples of a 2*2 matrix, two hours from now they may change the data struct to
1*4, or an array of 16*12*128,...)
One part of the problem is to generate the header line of the .CSV file. I need a method that can
generate an array of strings like this:
for a 2*2: data_0_0, data_0_1, data_1_0, data_1_1, and
for a 1*4: data_0, data_1, data_2, data_3,
for a 3*4*2: data_0_0_0, data_0_0_1, data_0_0_2,...., data_2_3_0, data_2_3_1,
and so on ...
The only information that I can get from the tool each time is the dimensions and size of the array.
The tool may tell me {1}, which means a single value, {12} means an array with a length of 12, {3,4,5}
means a " 3x4x5 " element array and so on and so forth... Therefore, I need to be able to flatten any array
of a*b*c*..*x. (which should not be too hard as I can have a single for loop.
So, I'd like to create a method that generates a vector of strings (in above format) from ANY multidimensional array.
Therefore I think at the end, the header generating method will lookalike something this
public string[] GenerateNames(string dataBlockName, int[] dimensions)
{
}
One simple solution is to have lets say 10 For-loops and hope that the raw data will never have an array that has more than 10 dimensions. However, I'm looking for a better, cleaner, nicer solution!
There are a lot of questions asking how to change a vector into multidimensional arrays. My goal is the exact opposite thing and a header line with unlimited flexibility!
Thanks a lot in advance fellas!
--
Someone below suggested to use "Depth First Traversal" which I am going to look into now. Initial googling seemed promising.
You can flatten any array by merely iterating it in a foreach loop, adding each item to a list, and then converting that list back to an array.
public T[] Flatten<T>(Array array)
{
var list = new List<T>();
foreach (T item in array)
{
list.Add(item);
}
return list.ToArray();
}
where array is a rectangular array of any shape.
You don't need the array with the size, as you can check the dimensions by using the Rank property of the Array class, and the corresponding methods for obtaining the values. With this in mind and the good old .net 1.0 Array class you can write a method like this one:
public T[] Flatten<T>(Array source)
{
var arrayIndex = new int[source.Rank];
var result = new T[Enumerable.Range(0, source.Rank).Sum(i => source.GetUpperBound(i))];
var index = 0;
for(var i = 0; i < source.Rank; i++)
{
for(var j = 0; j < source.GetUpperBound(i); j++)
{
arrayIndex[i] = j;
result[index++] = (T)source.GetValue(arrayIndex);
}
}
return result;
}
It's more convoluted than a foreach, but it will provide greater flexibility on how you could traverse the original array (which is dependent on the .net implementation). As Array is not a generic class you will need to provide the element type on the method, so that for an array of integers you can call it as:
Flatten<int>(myArray);
Buffer.BlockCopy is handy here.
Note: there are some special cases to deal with so take this as pseudocode.
public T[] Flatten<T>(Array source)
{
int byteCount = Buffer.ByteLength(source);
int sizeofT = Buffer.ByteLength(new T[1]);
T[] dest = new T[(byteCount + sizeofT - 1) / sizeofT];
Buffer.BlockCopy(source,0,dest,0,byteCount);
return dest;
}
Is there a potential 1 liner that allows me to create a new 1 dimensional array from a certain index of the inner array of the 2D?
Example take the first element of each inner array:
double[][] array2D = new double[10][] // with inner arrays say double[5]
double[] array1D = new double[10];
for (int i=0; i<array2D.Length; i++)
{
array1D[i] = array2D[i][0];
}
I'd just use LINQ. That won't "avoid loops" in terms of execution, but it'll avoid a loop in your source code:
// 1dArray isn't a valid identifier...
var singleArray = jaggedArray.Select(x => x[0]).ToArray();
Note that this relies on it being a jagged array (an array of arrays). It will not do what you expect for true multi-dimensional (rectangular) arrays.
Or slightly more efficiently:
var singleArray = Array.ConvertAll(jaggedArray, x => x[0]);
That's more efficient because it knows the output size to start with, and builds the array directly - but it's a bit less idiomatic than using LINQ these days (which is more generally applicable to all sequences, not just arrays).
I have an Array variable. I can use the Rank property to get the number of dimensions and I know that you can use a foreach to visit each element as if the array was flattened. However, I wish to modify elements and change element references. I cannot dynamically create the correct number of for loops and I cannot invalidate an enumerator.
EDIT
Thanks for the comments, sorry about the previous lack of clarity at the end of a long tiring day. The problem:
private void SetMultiDimensionalArray(Array array)
{
for (int dimension = 0; dimension < array.Rank; dimension++)
{
var len = array.GetLength(dimension);
for (int k = 0; k < len; k++)
{
//TODO: do something to get/set values
}
}
}
Array array = new string[4, 5, 6];
SetMultiDimensionalArray(array);
Array array = new string[2, 3];
SetMultiDimensionalArray(array);
I had another look before reading this page and it appears all I need to do is create a list of integer arrays and use the overloads of GetValue and SetValue -
Array.GetValue(params int[] indices)
Array.SetValue(object value, params int[] indices)
Everything seems clear now unless someone can suggest a superior method. svick has linked to this so I will accept this answer barring any further suggestions.
It's hard to tell what exactly do you need, because your question is quite unclear.
But if you have a multidimensional array (not jagged array) whose rank you know only at runtime, you can use GetValue() to get the value at specified indices (given as an array of ints) and SetValue() to set it.
hello i will much apreciate any help.
ok let's see, first i have declare a jagged array like this and the next code
int n=1, m=3,p=0;
int[][] jag_array =new[n];
now my jagged array will have 1 array inside, next y have to fill the array like this:
car=2;
do
{
jag_array[p]= new double[car];
for (int t = 0; t < carac; t++)
{
jag_array[p][t] = variableX;
}
p=p+1
}
while(p==0)
now my jagged array looks like this(also insert some data for this example):
jag_array[0][0]=4
jag_array[0][1]=2
now my question how can i insert a new array whit out losing my previos data if i declare
jag_array[p+1]= new double[car];
i will lose the data from the previos one, i will like to look something likes this:
jag_array[0][0]=4
jag_array[0][1]=2
jag_array[1][0]=5
jag_array[1][1]=6
the reason i did not declare from the begining 2 array is beacuse i dont know how many i am going to use it could be just 1 or 20 and every time i have to create a new array whit out losing the previous data that has been already fill, thaks all for the attention,
The size of an array, once created, is by definition invariable. If you need a variable number of elements, use a List<T> - in your case, probably a List<int[]>.
The only alternative solution would be to created a new array with the new size (and assign that to your jag_array variable) and copy all the previous elements from your old array into the new array. That is unnecessarily complicated code when you can just use List<T>, but if you cannot use List<T> for any reason, here is an example:
// increase the length of jag_array by one
var old_jag_array = jag_array; // store a reference to the smaller array
jag_array = new int[old_jag_array.Length + 1][]; // create the new, larger array
for (int i = 0; i < old_jag_array.Length; i++) {
jag_array[i] = old_jag_array[i]; // copy the existing elements into the new array
}
jag_array[jag_array.Length - 1] = ... // insert new value here