Converting List<T> to Array (multidimensional) [duplicate] - c#

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[][]

Related

Fill an array with unique random integers [duplicate]

This question already has answers here:
Randomize a List<T>
(28 answers)
Closed 5 years ago.
I want to fill a small array with unique values from a bigger array. How do I check the uniqueness?
Here's what I have:
int[] numbers45 = new int[45];
for (int i = 0; i <= 44; i++) // I create a big array
{
numbers45[i] = i + 1;
}
Random r = new Random();
int[] draw5 = new int[5]; //new small array
Console.WriteLine("The 5 draws are:");
for (int i = 1; i <= 4; i++)
{
draw5[i] = numbers45[r.Next(numbers45.Length)]; //I fill the small array with values from the big one. BUT the values might not be unique.
Console.WriteLine(draw5[i]);
}
There are multiple ways to do what you are asking.
First off, though, I would recommend to use one of the classes which wraps the array type and adds some extra functionality you could use (in this case a List would probably be a perfect structure to use)!
One way to handle this is to check if the value is already in the draw5 array. This can be done with (for example) the List<T>.Contains(T) function, and if it exists, try another.
Personally though, I would probably have randomized the first array with the OrderBy linq method and just return a random number, like:
numbers45.OrderBy(o => random.Next());
That way the numbers are already random and unique when it is supposed to be added to the second list.
And a side note: Remember that arrays indexes starts on index 0. In your second loop, you start at 1 and go to 4, that is, you wont set a value to the first index.
You could just run for (int i=0;i<5;i++) to get it right.
Inspired by Jite's answer, I changed to use Guid to randomize the numbers
var randomized = numbers45.OrderBy(o => Guid.NewGuid().ToString());
Then you could take the draws by:
var draws = randomized.Take(5).ToArray;
HashSet<int> hs = new HashSet<int>();
int next = random.next(45);
while(hs.Length <=5)
{
if(!hs.Contains(array[next]))
hs.Add(array[next]);
next = random next(45);
}

I need help figuring out how to work with c# matrix [duplicate]

This question already has answers here:
What is a jagged array?
(7 answers)
Closed 5 years ago.
I'm trying to understand how to work with matrix in C#.
I used to code in Java:
int[][]arr=new int[2][5]; or
int [][]arr={{2,3,4,5},{9,3}};
When I try to create an array in C# I only success to make this way:
int[,]={{1,2,3,4},{5,6,7,8}};
This line works for me but it requires same length in every column. I also try to use GetLength() when I worked with for loops and I could get only the number of columns and the size of the second column.
Is there any way to create a matrix with any size I want like the java examples?
How can I get the size of the rows/columns?
Is there any way to create a matrix with any size I want like the java examples
The term for such matrices is jagged array. Unlike int[,], this is an array of arrays; you can create it like this:
int [][] arr= { new[] {2,3,4,5}, new[] {9,3} };
How can I get the size of the rows/columns?
Now that this is an array of arrays, you can access Length of each item in arr the same way that you do in Java:
for (var r = 0 ; r != arr.Length ; r++) {
Console.WriteLine("Row {0} has {1} columns.", r, arr[r].Length);
for (var c = 0 ; c != arr[r].Length ; c++) {
...
}
}

Can LINQ construct and return a multidimensional array

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

How can I change an 2D array to a 2D list and then back to a 2D array again?

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

C#: double[][] and double[,] [duplicate]

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[,]).

Categories