This question already has answers here:
Differences between a multidimensional array "[,]" and an array of arrays "[][]" in C#?
(12 answers)
Why we have both jagged array and multidimensional array?
(13 answers)
Closed 9 years ago.
I confuse between double[][] and double[,] in C#.
My teammate give me a function like this:
public double[][] Do_Something(double[][] A)
{
.......
}
I want to use this function:
double[,] data = survey.GetSurveyData(); //Get data
double[,] inrma = Do_Something(data);
It lead an error: invalid argument.
I don't want to edit my teammate's code.
Does it have any way to convert double[][] to double [,] ?
Thanks!
A double[][] is an array of double[] (An array of arrays)
but double[,] is a single 2 dimensional double array
Example :
double[] Array1 = new double[] {1,2,3};
double[] Array2 = new double[] {4,5,6};
double[][] ArrayOfArrays = new double[][] {Array1,Array2};
double[,] MultidimensionalArray = new double[,] {{1,2}, {3,4}, {5,6}, {7,8}};
double[][] and double[,] have different meanings.
double[][] is jagged, so some elements can be of different lengths than others.
double[,] is "rectangular", so all elements are of the same length.
You could write a method to "convert" between the two, but how will you rectify the differences? I.e. how will you decide to "trim" from the long elements or expand the short elements in order to make it rectangular?
static T[,] Convert<T>(T[][] array)
{
if (array == null)
throw new ArgumentNullException("array");
if (array.Length == 0)
return new T[0, 0];
T[,] retval = new T[array.Length, array[0].Length];
for (int i = 0; i < array.Length; i++)
for (int j = 0; j < array[i].Length; j++)
if (array[i].Length != retval.GetLength(1))
throw new Exception();
else
retval[i, j] = array[i][j];
return retval;
}
They are two different types of arrays.
double[][] is a jagged array, which is an array of arrays; each of these arrays can have a different length, which leads to a problem.
double[,] is just a multidimensional array. Each row will have an equal number of columns and each column will have an equal number of rows.
This size difference causes a problem since the jagged array could really be different dimensions for different rows. You could write a method to convert between the two if you knew the exact dimensions of the jagged array, but in that case I would suggest rewriting the original method to accept and return a multidimensional array (double[,]).
Related
Yes, I do know the difference between a jagged array [][] and a multidimensional array [,].
Yes, I have looked for duplicates and found these:
How to use LINQ on a multidimensional array to 'unwind' the array?
Convert 2 dimensional array
c# linq return a multidimensional array from linq
The last one of these contains a function to do the job. But my question is still: is there any way (no matter how contorted or contrived) to persuade LINQ to construct and return a result in the form of a multidimensional array (and not a jagged array)?
It's not really relevant to the question, but the problem that led here was one of those little jobs that looked like it was "made for LINQ", except that the function I needed to call had been defined with a multidimensional array parameter. The LINQ code to produce the answer as a jagged array took about 5 minutes to write, and then what? Did I miss something, or is there really no way for LINQ to do the job?
I supposed I should say: other than writing a chunk of code to do it the old way and embedding it as a lambda or calling it as an extension method. For now it does look as if LINQ can neither produce nor consume multidimensional arrays, and the answer to my question is no.
Uhm.. well.. sure? This is an example how to turn list of integers into 2 dimensional array if possible.
void Main()
{
var wat = new[]{2, 4, 5, 6, 7, 8}
.Select(x => new { dummy=1, val= x})
.GroupBy(x => x.dummy) // group everything into one, "UNFLATTEN"
.Select(gr =>
{
var elements = gr.Select(x => x.val).ToList();
if(elements.Count == 0 || elements.Count % 2 != 0)
throw new NotSupportedException("I don't know what to do.");
var halfSize = elements.Count / 2;
int[,] ret = new int[2, halfSize];
for(var k = 0; k < halfSize; k++){
ret[0, k] = elements[k];
ret[1, k] = elements[elements.Count - halfSize + k];
}
return ret;
}
).First();
wat.Dump();
}
Output:
_ 0 1 2
0 2 4 5
1 6 7 8
As others have said, you're best off by creating new extension method:
static class LinqExtensions
{
public static T[,] ToRectangularArray<T>(this IEnumerable<IEnumerable<T>> arrays)
{
// TODO: Validation and special-casing for arrays.Count == 0
// TODO: Rename "arrays"
// TODO: Make sure that Count() is used only once,
// TODO: ElementAt() does not work everywhere, you're better off using ToList() before!
int minorLength = arrays.First().Count();
T[,] ret = new T[arrays.Count(), minorLength];
for (int i = 0; i < arrays.Count(); i++)
{
var array = arrays.ElementAt(i);
if (array.Count() != minorLength)
{
throw new ArgumentException
("All arrays must be the same length");
}
for (int j = 0; j < minorLength; j++)
{
ret[i, j] = array.ElementAt(j);
}
}
return ret;
}
}
void Main()
{
var wat = new[]{new[]{2, 4, 5}, new[]{6, 7, 8}}.ToRectangularArray();
wat.Dump();
}
for convienence, you might want to add the same extension method for IEnumerable<T>, and call it as such: ToRectangularArray<T>(this IEnumerable<T> input, int dimensions = 2)
I supposed I should say: other than writing a chunk of code to do it
the old way and embedding it as a lambda or calling it as an extension
method. For now it does look as if LINQ can neither produce nor
consume multidimensional arrays, and the answer to my question is no.
It is no. Most LINQ methods are extension methods of IEnumerable<T>. While a jagged array (say, int[int[]]) implements IEnumerable<int[]>, a multidimensional array doesn't implement IEnumerable<T>, so you can't use any LINQ extension method.
The only thing you could do is to eventually return a multidimensional array using a projection (Select).
I thought searching SO would show me a hit regarding 2D lists to 2D arrays but it seems it's not as common as I had thought.
This is what I've got:
// init array
int[][] a = new int[10][10];
// change 2D array to 2D list
List<List<int>> b = a.Cast<List<int>>().ToList();
// change 2D list back to 2D array
???
How can I change b back to a 2D array? Also is the above correct?
Something like this:
List<List<int>> lists = arrays.Select(inner=>inner.ToList()).ToList();
int[][] arrays = lists.Select(inner=>inner.ToArray()).ToArray();
It's totally wrong. You can't get b in that way. And even the initialization is wrong. And in .NET there are two types of multidimensional arrays... True multidimensional arrays and jagged arrays...
Let's start... You are using a jagged array (I won't tell you what it's, or the difference, you didn't ask for it... if you need them, google for it)
int[][] a = new int[10][]; // see how you define it?
// Only the first dimension can be is sized here.
for (int i = 0; i < a.Length; i++)
{
// For each element, create a subarray
// (each element is a row in a 2d array, so this is a row of 10 columns)
a[i] = new int[10];
}
Now you have defined a 10x10 array jagged array.
Now a little LINQ:
You want a list:
List<List<int>> b = a.Select(row => row.ToList()).ToList();
you want back an array:
int[][] c = b.Select(row => row.ToArray()).ToArray();
The first expression means
foreach element of a, we call this element row `a.Select(row =>` <br>
make of this element a List `row.ToList()` and return it<br>
of all the results of all the elements of a, make a List `.ToList();`
The second is specular.
Now... Just out of curiosity, and if you had a true multidimensional array? then it was complex, very comples.
int[,] a = new int[10,10];
int l0 = a.GetLength(0);
int l1 = a.GetLength(1);
var b = new List<List<int>>(
Enumerable.Range(0, l0)
.Select(p => new List<int>(
Enumerable.Range(0, l1)
.Select(q => a[p, q]))));
var c = new int[b.Count, b[0].Count];
for (int i = 0; i < b.Count; i++)
{
for (int j = 0; j < b[i].Count; j++)
{
c[i, j] = b[i][j];
}
}
With a tricky (and horrible) LINQ expression we can "convert" a multidimensional array to a List<List<int>>. The road back isn't easily doable with LINQ (unless you want to use the List<T>.ForEach() that you shouldn't ever use, because it's not kosher, and then List<T>.ForEach() isn't LINQ)... But it's easily doable with two nested for ()
I want to store ARRAY from 3 dimensional array into buildingCostIds, but it says I MUST have 3rd number.
public static int[, ,] buildingCost = { {{0,1,2},{5,5,5}}};
public static void addBuilding(int[] ids, int[] amounts, int buildingId)
{
int[] buildingCostIds = buildingCost[buildingId, 0, *];
}
*I need third number here, but I don't want it because it will extract just number, I want whole array!
PROBLEM SOLVED, solution:
public static Array extractArray(int dim1, int dim2)
{
int[] tempArray = { };
for (int number=0;number<=2; number++)
{
tempArray[number] = buildingCost[dim1, dim2, number];
}
return tempArray;
}
This might be simpler if you use an array-of-arrays, or jagged array [][][] like
int[][][] buildingCost = new int[2][][];
Then you can access buildingCost[buildingId, 0] which is an array of ints.
There is a related question here
EDIT
Be aware the "problem solved" you added to the question duplicates the data, so you may run out of memory if you keep doing this.
Consider using a List of Lists of Lists and lazy evaluating what you need.
Try This
int[, ,] array3D = new int[3,3,3]
I've got a two-dimensional array like this:
double[,] results = new double[100,100];
I'd like to pass every one dimensional part of the array to a function as a paremeter.
for (int i = 0; i < 100; i++){
cool_function (results[???], 10);
}
How do I do this in C#?
source
Jagged arrays are arrays of arrays. The elements of a jagged array are other arrays.
Declaring Jagged Arrays
Declaration of a jagged array involves two brackets. For example, the following code snippet declares a jagged array that has three items of an array.
int[][] intJaggedArray = new int[3][];
The following code snippet declares a jagged array that has two items of an array.
string[][] stringJaggedArray = new string[2][];
Initializing Jagged Arrays
Before a jagged array can be used, its items must be initialized. The following code snippet initializes a jagged array; the first item with an array of integers that has two integers, second item with an array of integers that has 4 integers, and a third item with an array of integers that has 6 integers.
// Initializing jagged arrays
intJaggedArray[0] = new int[2];
intJaggedArray[1] = new int[4];
intJaggedArray[2] = new int[6];
We can also initialize a jagged array's items by providing the values of the array's items. The following code snippet initializes item an array's items directly during the declaration.
// Initializing jagged arrays
intJaggedArray[0] = new int[2]{2, 12};
intJaggedArray[1] = new int[4]{4, 14, 24, 34};
intJaggedArray[2] = new int[6] {6, 16, 26, 36, 46, 56 };
You can't do it without copying the corresponding part of the array.
Otherwise, you can use a double[][]. To initialize:
double[][] results = new double[100][];
for(int i = 0; i < 100; i++)
results[i] = new double[100];
You could do this by using a jagged array Type[][] instead of Type[,]. In this case you can just pass array[index]. Otherwise you will have to either pass the two-dimensional array together with the index of the subarray of interest and perform the indexing in the called method or create a copy of the subarray of interest.
If you mean for an array myarray[x][y] that you want to call a function for x arrays of size y then all you need is the following code:
int i;
for (i = 0; i < 100; i++)
{
cool_function(array[i], 10);
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I convert a list<> to a multi-dimensional array?
I want to have an array in form of double[,] for this purpose since I do not know what will be the length of this array, I want to make a List first then later using List<T>.ToArray() convert it to double[,]:
public double[,] FilterClampedData(double[,] data)
{
var finalData = new List<double[]>();
//Do some stuff on parameter
return finalData.ToArray(); ///Does not compile :(
}
Since ToArray returns a one-dimensional array, there is no wonder why this does not compile. If you were returning double[][], it would compile, however. You could also build your 2-D array manually with two nested loops:
var R = finalData.Count;
var C = finalData[0].Length;
var res = new double[R, C];
for (int r = 0 ; r != R ; r++)
for (int c = 0 ; c != C ; c++)
res[r, c] = finalData[r][c];
return res;
The code above assumes that you have at least one item in the finalData, and that the length of all lists inside finalData is the same.
Instantiate a new double array with the largest size [length of the list, largest array length in the list]
Walk through the list with double for cycle (first on the list, the nested on the current list item) and fill the new array
finalData.ToArray() will produce double[][] because:
List<T>.ToArray() returns T[]
List<T[]>.ToArray() returns T[][]