Add Multidimensional Array To List - c#

I have a multidimensional double array with any number of rows and columns:
var values = new double[rows, columns];
I also have a list of double arrays:
var doubleList = new List<double[]>();
Now, I would like to add each column in the multidimensional array to the list. How do I do that? I wrote this to illustrate what I want, but it does not work as I am violation the syntax.
for (int i = 0; i < columns; i++)
{
doubleList.Add(values[:,i];
}

var values = new double[rows, columns];
var doubleList = new List<double[]>();
for (int i = 0; i < columns; i++)
{
var tmpArray = new double[rows];
for (int j = 0; j < rows; i++)
{
tmpArray[j] = values[j, i];
}
doubleList.Add(tmpArray);
}

You will need to create a new array for each column and copy each value to it.
Either with a simple for-loop (like the other answers show) or with LINQ:
for (int i = 0; i < columns; i++)
{
double[] column = Enumerable.Range(0, rows)
.Select(row => values[row, i]).ToArray();
doubleList.Add(column);
}

With the approach you were taking:
for(int i = 0; i != columns; ++i)
{
var arr = new double[rows];
for(var j = 0; j != rows; ++j)
arr[j] = values[j, i];
doubleList.Add(arr);
}
Build up the each array, per row, then add it.
Another approach would be:
var doubleList = Enumerable.Range(0, columns).Select(
i => Enumerable.Range(0, rows).Select(
j => values[j, i]).ToArray()
).ToList()
Which some would consider more expressive in defining what is taken (values[j, i] for a sequence of i inner sequence of j) and what is done with them (put each inner result into an array and the result of that into a list).

Related

Create an Array of arrays of arrays of different shapes

I am trying to create an array of 6 arrays each containing 4 arrays, each of those 4 arrays with different shape.
Like in the form below:
[[array([[1,2,3,4,6,5],
[5,6,6,7,7,5],
[6,6,5,5,6,5],
[4,6,6,7,7,5],
[5,6,6,7,7,5],
[6,6,5,5,6,5],
[6,6,5,5,6,5],]),
array([[9,9,9],
[9,9,9],
[6,6,6],
[3,3,6],
[6,6,6]]),
array([[6],
[7],
[7],
[7],
[7]]),
array([[7,8,8,8,8]])],
[[array([[1,2,3,4,6,5],
[5,6,6,7,7,5],
[6,6,5,5,6,5],
[4,6,6,7,7,5],
[5,6,6,7,7,5],
[6,6,5,5,6,5],
[6,6,5,5,6,5],]),
array([[9,9,9],
[9,9,9],
[6,6,6],
[3,3,6],
[6,6,6]]),
array([[6],
[7],
[7],
[7],
[7]]),
array([[7,8,8,8,8]])]]
..........
I have this code but I am doing something wrong, I do not get the desired shape.
Can somebody please help me with this?
int populationSize = 6;
double[][][][] population = new double[populationSize][][][];
int value = 3;
for (int i = 0; i < populationSize; i++)
{
population[i] = new double[4][][];
for (int j = 0; j < 4; j++)
{
const int rows = 7, cols = 6;
population[i][j] = new double[rows][];
for (int k = 0; k < rows; k++)
{
population[i][j][k] = new double[cols];
for (int m = 0; m < cols; m++)
{
population[i][j][k][m] = value;
}
}
}
}
const int rows = 7, cols = 6;
population[j][j] = new double[5][];
for (int k = 0; k < rows; k++)
you are using the same indexes for population[j][j], that is probably incorrect.
You are also specifying 7 rows, but create a matrix of size 5. That is probably incorrect.
As Scopperloit points out, you probably want:
const int rows = 7, cols = 6;
population[i][j] = new double[rows][];
for (int k = 0; k < rows; k++)
Overall when debugging problems. Run the code in a debugger and inspect the values against your expectations. Index out of range exceptions are usually very easy to debug:
What is the index?
What is the length of the array?
Is the index or array length incorrect?
I managed to solve my problem.
THis function creates an array of arrays of arrays of different shapes according to another array, and fills it with random normal standard distribution values :
int[,] netshape = new int[,] { { 3, 4}, { 4, 5}, { 4, 1 }, { 1, 4} }; // The shape of the network
public double[][][][] CreateNetwork(int[,] netshape,int populationSize )
{
normal = new MathNet.Numerics.Distributions.Normal(0, 1);// Generate random normal standard distribution
int rows, cols ;
double[][][][] population = new double[populationSize][][][];
for (int i = 0; i < populationSize; i++)
{
population[i] = new double[4][][];
for (int j = 0; j < 4; j++)
{
rows = netshape[j, 0];
cols = netshape[j, 1];
population[i][j] = new double[rows][];
for (int k = 0; k < rows; k++)
{
population[i][j][k] = new double[cols];
for (int m = 0; m < cols; m++)
{
population[i][j][k][m] = normal.Sample(); ;
}
}
}
}
return population;
}

Do you always have to start at the index zero when writing a 2D list?

I want to fill in a 2Dlist, but start at the third position [2]. Is this somehow possible?
A short code for understanding what i mean:
List<List<string>> List2D = new List<List<string>>();
for (int i = 0; i < 5; i++)
{
List2D[2].Add("i")
}
I get the following error:
Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
EDIT: Any idea how to fill in a 4D list?
List<List<List<List<string>>>> List4D = new List<List<List<List<string>>>>();
for (int i = 0; i < List1.Count; i++)
{
List<List<List<string>>> List3D = new List<List<List<string>>>();
for (int j = 0; j < List2.Count; j++)
{
List<List<string>> List2D = new List<List<string>>();
for (int k = 0; k < List3.Count; k++)
{
List<string> Lijst1D = new List<string>();
List2D.Add(Lijst1D);
}
List3D.Add(List2D);
}
List4D.Add(List3D);
}
So later I can call: List4D[2][3][0].Add("test");
Since you just created your List2D and not added any nested list into it, you can't access its third element (there is nothing there).
You have to add some items first:
List<List<string>> List2D = new List<List<string>>();
List2D.Add(new List<string>());
List2D.Add(new List<string>());
List2D.Add(new List<string>());
for (int i=0; i<5; i++)
{
List2D[2].Add("i")
}
Update
Well, core idea of filling that list remains the same: if you want to access List4D[2][3][0] - first you need to fill all of lists in "path".
You can do it something like this:
List<List<List<List<string>>>> List4D = new List<List<List<List<string>>>>();
int i1 = 2, i2 = 3, i3 = 0;
for (int i = 0; i <= Math.Max(i1, 1); i++)
List4D.Add(new List<List<List<string>>>());
for (int i = 0; i <= Math.Max(i2, 1); i++)
List4D[i1].Add(new List<List<string>>());
for (int i = 0; i <= Math.Max(i3, 1); i++)
List4D[i1][i2].Add(new List<string>());
List4D[i1][i2][i3].Add("test");
Frankly, idea of 4D list looks a little bit "syntetic". In real application probably it is not the best data structure because of clumsy addressing.

How to convert jagged array to 2D array?

I have a file file.txt with the following:
6,73,6,71
32,1,0,12
3,11,1,134
43,15,43,6
55,0,4,12
And this code to read it and feed it to a jagged array:
string[][] arr = new string[5][];
string[] filelines = File.ReadAllLines("file.txt");
for (int i = 0; i < filelines.Length; i++)
{
arr[i] = filelines[i].Split(',').ToArray();
}
How would I do the same thing, but with a 2D array?
Assuming you know the dimensions of your 2D array (or at least the maximum dimensions) before you start reading the file, you can do something like this:
string[,] arr = new string[5,4];
string[] filelines = File.ReadAllLines("file.txt");
for (int i = 0; i < filelines.Length; i++)
{
var parts = filelines[i].Split(','); // Note: no need for .ToArray()
for (int j = 0; j < parts.Length; j++)
{
arr[i, j] = parts[j];
}
}
If you don't know the dimensions, or if the number of integers on each line may vary, your current code will work, and you can use a little Linq to convert the array after you've read it all in:
string[] filelines = File.ReadAllLines("file.txt");
string[][] arr = new string[filelines.Length][];
for (int i = 0; i < filelines.Length; i++)
{
arr[i] = filelines[i].Split(','); // Note: no need for .ToArray()
}
// now convert
string[,] arr2 = new string[arr.Length, arr.Max(x => x.Length)];
for(var i = 0; i < arr.Length; i++)
{
for(var j = 0; j < arr[i].Length; j++)
{
arr2[i, j] = arr[i][j];
}
}

Delete row of 2D string array in C#

I am making a program that stores data in a 2D array. I would like to be able to delete rows from this array. I cannot figure out why this code doesn't work:
for (int n = index; n < a.GetUpperBound(1); ++n)
{
for (int i = 0; i < a.GetUpperBound(0); ++i)
{
a[i, n] = a[i, n + 1];
}
}
Could someone please help me out? I would like it to delete a single row and shuffle all the rows below it up one place. Thankyou!
you need to create a new array if you want to delete an item
try something like this
var arrayUpdated = new string[a.GetUpperBound(1)][a.GetUpperBound(0)-1];
for (int n = index; n < a.GetUpperBound(1); n++)
{
for (int i = 0; i < a.GetUpperBound(0); i++)
{
arrayUpdated [i, n] = a[i, 1];
}
}
The nested for loop method here works well: https://stackoverflow.com/a/8000574
Here's a method that converts the outer loop of the [,] array method above to use linq. Using linq here is only recommended if you are also doing other things with linq during the traversal.
public T[,] RemoveRow<T>(T[,] array2d, int rowToRemove)
{
var resultAsList = Enumerable
.Range(0, array2d.GetLength(0)) // select all the rows available
.Where(i => i != rowToRemove) // except for the one we don't want
.Select(i => // select the results as a string[]
{
T[] row = new T[array2d.GetLength(1)];
for (int column = 0; column < array2d.GetLength(1); column++)
{
row[column] = array2d[i, column];
}
return row;
}).ToList();
// convert List<string[]> to string[,].
return CreateRectangularArray(resultAsList); // CreateRectangularArray() can be copied from https://stackoverflow.com/a/9775057
}
used Enumerable.Range to iterate all rows as done in https://stackoverflow.com/a/18673845
Shouldn't ++i be i++? ++i increments before matrix operation is performed(ie pre-increment)

Multi-Dimensional Data Structures in C#

How do you create a multi-dimensional data structure in C#?
In my mind it works like so:
List<List<int>> results = new List<List<int>>();
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
results[i][j] = 0;
}
}
This doesn't work (it throws an ArgumentOutOfRangeException). Is there a multi-dimensional structure in C# that allows me to access members through their indexes?
The problem here is that List doesn't automatically create elements. To initialise a List<List<T>> you need something like this:
List<List<int>> results = new List<List<int>>();
for (int i = 0; i < 10; i++)
{
results.Add(new List<int>());
for (int j = 0; j < 10; j++)
{
results[i].Add(0);
}
}
Note that setting Capacity is not sufficient, you need to call Add the number of times you need. Alternatively, you can simplify things by using Linq's Enumerable class:
List<List<int>> results = new List<List<int>>();
for (int i = 0; i < 10; i++)
{
results.Add(new List<int>());
results[i].AddRange(Enumerable.Repeat(0, 10));
}
Again, note that Enumerable.Repeat(new List<int>(), 10) will not work, since it will add 10 references to the same list.
Another approach using Linq to the extreme:
List<List<int>> results = Enumerable.Repeat(0, 10)
.Select(i => Enumerable.Repeat(0, 10).ToList())
.ToList();
(The unused parameter i is necessary to ensure that you don't reference the same list ten times as discussed above.)
Finally, to access elements, you can use exactly the notation you used before. Once the elements have been added, they can be read or modified as shown:
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
results[i][j] = 2;
int x = results[i][j];
}
}
If you know the dimensions of your structure in advance, and you do not plan to add or remove elements, then a 2D array sounds like your thing:
int[,] n = new int[10, 20];
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
n[i, j] = ...
};
};
You have to create the lists and initialize them with zeros before you can't start indexing into them.
List<List<int>> results = new List<List<int>>();
for (int i = 0; i < 10; i++)
{
results.Add(new List<int>(Enumerable.Repeat(0, 10)));
}
You have to actually 1) create each of the inner lists, and 2) set them to that size.
var Results = Enumerable.Range(0, 10).Select(i => Enumerable.Repeat(0, 10).ToList()).ToList();
I'm a bit of a Linq addict, though.
You could use a datatable and add columns and rows? You would then be able to reference them by name or index.

Categories