I have a 2D array of type string which I want to modify and resize inside some loop. My main goal is to use minimum memory by creating a 2d array which will be modified every iteration of loop and the add a char to an appropriate cell in this array. Here is my code:
static void Main(string[] args)
{
int maxBound = 100;//length of freq array
Random rnd1 = new Random();
int numLoops = rnd1.Next(1000, 1200);//number of total elements in freq array
int[] freq = new int[maxBound];//freq array
string[,] _2dim = new string[maxBound, numLoops];//rows,columns
Random rnd2 = new Random();
for (int i = 0; i < numLoops; i++)
{
int s = rnd2.Next(maxBound);
freq[s]++;
//Here I try to add `*` to the _2dim array while resizing it to the appropriate size
}
}
What is the main approach for the solution ? Thanks
Instead of a 2D array you might want to use a jagged one. Briefly, a 2D array is always an N x M matrix, which you cannot resize, whereas a jagged array is an array of arrays, where you can separately initialize every inner element by a different size (see the differences in details here)
int maxBound = 100;
Random rnd = new Random();
int numLoops = rnd.Next(1000, 1200);
string[][] jagged = new string[numLoops][];
for (int i = 0; i < numLoops; i++)
{
int currLen = rnd.Next(maxBound);
jagged[i] = new string[currLen];
for (int j = 0; j < currLen; j++)
jagged[i][j] = "*"; // do some initialization
}
You should use a list of type string nested in a List. Then you can modify this lists. For iterating through this you should use two for loops.
List<List<string>> l = new List<List<string>> { new List<string> { "a", "b" }, new List<string> { "1", "2" } };
Iteration example:
for(int i = 0; i < l.Count; i++)
{
for(int j = 0; j < l[i].Count; j++)
{
Console.WriteLine(l[i][j]);
}
}
Related
As done here: C # Two-dimensional int array,Sum off all elements, but this time with jagged arrays. Getting:
System.IndexOutOfRangeException.
I am a beginner asking for help. This is my code:
public static int Sum(int[][] arr)
{
int total = 0;
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
total += arr[i][j];
}
}
return total;
}
static void Main(string[] args)
{
int[][] arr = new int[][]
{
new int [] {1},
new int [] {1,3,-5},
};
int total = Sum(arr);
Console.WriteLine();
Console.ReadKey();
}
In your inner loop do this instead:
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] != null)
{
for (int j = 0; j < arr[i].Length; j++)
{
total += arr[i][j];
}
}
}
return total;
Because your lists aren't even you get the exception on arr.GetLength(1) for the first dimension - it has no item at that place.
The if (arr[i] != null) line is needed in the case the array would look something like:
int[][] arr = new int[][]
{
new int [] {1},
null,
new int [] {1,3,-5},
};
In this case, when we loop with i==1 and try to do arr[i].Length (meaning arr[1].Length we will recieve a NullReferenceException.
And after you do the basics and get to Linq all your current Sum method can be replaced with:
arr.SelectMany(item => item).Sum()
But it is good to start with the basics :)
Since you're using a jagged array the dimensions of that array aren't necessarily even. Have a look at the initialization code of that jagged array:
int[][] arr = new int[][] {
new int [] {1},
new int [] {1,3,-5},
};
So in the first dimension, there are two elements ({1} and {1, 3, -5}). But the second dimension isn't of the same length. The first element has got only one element ({1}) whereas the second element's got 3 elements ({1, 3, -5}).
That's why you're facing the IndexOutOfRangeException.
To fix that, you'll have to adjust the inner loop to the number of elements for that dimension. You can do that like this:
for (int i = 0; i < arr.Length; i++) {
for (int j = 0; j < arr[i].Length; j++) {
total += arr[i][j];
}
}
I want to create an Array or a List with N-Dimensions.
Is there a way to do this without having a Method for each possible dimension:
private ____ createArray(int dimensions, int[] lengths)
{
// declare array with dimensions from variable dimensions
// set length of first dimension to lengths[0]
// set length of second dimension to lengths[1]
// [...]
// return array
}
And not like this
private int[][][] create3DArray(int[] lengths)
{
int[][][] array = new int[lengths[0]][][];
int[] newLengths = new int[lengths.Count - 1];
for(int i = 0; i < lengths.Count - 1; i++)
{
newLengths[i] = lengths[i + 1];
}
for(int i = 0; i < lengths[0]; i++)
{
array[i] = create2DArray(newLengths);
}
return array;
}
private int[][] create2DArray(int[] lengths)
{
int[][] array = new int[lengths[0]][];
for(int i = 0; i < lengths.Count; i++)
{
array[i] = new int[lengths[1]];
}
return array;
}
If I have to do it like this, I need to have a method for every possible (let's ignore the fact that it may not make sense to have an array with N-Dimensions) amount of dimensions.
you can create a list of lists:
var myList = new List<List<int>>();
for(int i = 0; i < 10; ++i) {
var localList = new List<int>();
myList.Add(localList);
}
You could create like this using Enumerable.Repeat as many levels as you want:
int x = 5, y = 6, z = 7;
List<List<List<int>>> list3D = Enumerable.Repeat<List<List<int>>>(
new List<List<int>>(
Enumerable.Repeat<List<int>>(
new List<int>(
Enumerable.Repeat<int>(0, z)
), y)
), x
).ToList();
}
In the example above you create 3D lists with initial value of 0 and initial size of 5x6x7
It is possible.
Make an int array of dimensions. From there, you can create a conditional var declaration. The only trick is that you need to make explicit the conversion to (Array)
Consider the following array:
private int[][] Blocks;
How can I specify each of this array's sizes separately?
Something like so was my first idea: (throws an error though)
Blocks = new int[5][];
Blocks = new int[][7];
Errors come as following:
Wrong number of indices inside []; expected 1
Array creation must have array size or array initializer
Invalid rank specifier ',' or ']'
There are two ways of declaring arrays in two dimensions.
True 2-dimensional arrays
Jagged arrays
A two dimensional array is one single array with two dimensions, i.e. one matrix. It has a rectangular shape:
int[,] twoDimensionalArray = new int[5, 7];
You can loop through all elements of a two dimensional array like this:
for (int i = 0; i < twoDimensionalArray.GetLength(0); i++) {
for (int j = 0; j < twoDimensionalArray.GetLength(1); j++) {
int element = twoDimensionalArray[i, j];
// TODO: Do something with element.
}
}
If the array is of constant size, declare constants for the size:
const int ArrWidth = 5, ArrHeight = 7;
int[,] twoDimensionalArray = new int[ArrWidth, ArrHeight];
for (int i = 0; i < ArrWidth; i++) {
for (int j = 0; j < ArrHeight; j++) {
int element = twoDimensionalArray[i, j];
// TODO: Do something with element.
}
}
You can also enumerate all elements of a multi-dimensional array as a flattened enumeration with foreach:
foreach (int element in twoDimensionalArray) {
// TODO: Do something with element.
}
A jagged array is an array of arrays. You must create the array in two steps:
// First create the base (or outer) array
int[][] jaggedArray = new int[5][];
// Then create the nested (or innner) arrays
jaggedArray[0] = new int[7];
jaggedArray[1] = new int[2];
jaggedArray[2] = new int[11];
jaggedArray[3] = new int[0];
jaggedArray[4] = new int[4];
Because the nested arrays can have different sizes, this type of array is called "jagged".
You can loop through all elements of a jagged array like this:
for (int i = 0; i < jaggedArray.Length; i++) {
int[] inner = jaggedArray[i];
if (inner != null) {
for (int j = 0; j < inner.Length; j++) {
int element = inner[j];
// TODO: Do something with element.
}
}
}
You can leave out the null-test, if you know that you have initialized all inner arrays.
This
int[][] blocks = ...
is an array of arrays.
what you want probably, is a 2-dimensional array, which is declared like this:
int[,] blocks = new int[5,7];
If you really want an array of arrays, you can only declare the first 'dimension' like this:
int[][] block = new int[5][];
This creates an array of 5 (nulls).
Now you have to create each of those 'subarrays' like this:
block[0] = new int[3];
block[1] = new int [20];
The dieffernece here is, that each "subarray" can have a totally different size, compared to the 2-dimensional array.
what do you declare is an array of arrays so you have two cases.
Blocks = new int[5][];
the first is the size of the content of the array have same dimension
for (int i = 0; i < Blocks.Length; i++)
Blocks[i] = new int[8];
the second is the size of the content of the array have different dimension:
Blocks[0] = new int[6];
Blocks[1] = new int[4];
Blocks[2] = new int[10];
Blocks[3] = new int[7];
Blocks[4] = new int[3];
I have a problem, I need put an array in a DataGridView, I have the next code, but only I obtain the positions of the array with the rows, but the rows are empty...
Can anyone help me?
int[] arrays = new int [CaminoHormiga.Length];
string periodohorario = string.Empty;
for (int i = 0; i < CaminoHormiga.Length; i++)
{
arrays = CaminoHormiga;
periodohorario = arrays[i].ToString();
hg.dgHorarioGen.DataSource = arrays;
}
Try this
List<int> arrays = new List<int>();
for (int i = 0; i < CaminoHormiga.Length; i++)
{
arrays.Add(CaminoHormiga);
}
hg.dgHorarioGen.DataSource = arrays;
I currently have a jagged array Class[][][] which I want to serialise as a normal Class[] array, then convert back into a Class[][][] array after deserialization. Is it at all possible to convert between the two both ways? The dimensions are of constant sizes.
This is how you can flatten to a 1-dimensional structure:
var jagged = new object[][][];
var flattened = jagged.SelectMany(inner => inner.SelectMany(innerInner => innerInner)).ToArray();
As for going back to multidimensional - this will depend entirely on what it is your trying to achieve/what the data represents
If you don't mind serializing a flattened array and an array of ints, you can use the following:
public static int[] JaggedSizes<T>(this T[][][] topArray)
{
List<int> rtn = new List<int>();
rtn.Add(topArray.Length);
for (int i = 0; i < topArray.Length; i++)
{
var midArray = topArray[i];
rtn.Add(midArray.Length);
for (int j = 0; j < midArray.Length; j++)
{
var botArray = midArray[j];
rtn.Add(botArray.Length);
}
}
return rtn.ToArray();
}
// Thanks #Dave Bish
public static T[] ToFlat<T>(this T[][][] jagged)
{
return jagged.SelectMany(inner =>
inner.SelectMany(innerInner => innerInner)).ToArray();
}
public static T[][][] FromFlatWithSizes<T>(this T[] flat, int[] sizes)
{
int inPtr = 0;
int sPtr = 0;
int topSize = sizes[sPtr++];
T[][][] rtn = new T[topSize][][];
for (int i = 0; i < topSize; i++)
{
int midSize = sizes[sPtr++];
T[][] mid = new T[midSize][];
rtn[i] = mid;
for (int j = 0; j < midSize; j++)
{
int botSize = sizes[sPtr++];
T[] bot = new T[botSize];
mid[j] = bot;
for (int k = 0; k < botSize; k++)
{
bot[k] = flat[inPtr++];
}
}
}
return rtn;
}
I don't think so Rory.
You may have been able to do this if it is a Class[,,] multidimensional array, but the fact that each array could be of different length is going to always be a stumbling block.
Assuming you serialize if as a Class[] + another class to give you the original dimensions, you'll be golden.