tags:

views:

112

answers:

4

Is there an one-liner (no looping) that converts List<double[]> to double[,]?

A: 

If a 2 dim array is to be created from List of 1 dim array then looping is required, though it may not look like that at the call-site.

Hemal Pandya
+4  A: 

Converting to double[,] can only be done by looping through the list and requires that all arrays contained in the list are of same size:

double[,] arr = new double[list.Count, list[0].Length];
for (int i = 0; i < list.Count; i++)
{
    for (int j = 0; j < list[0].Length; j++)
    {
        arr[i, j] = list[i][j];
    }
}

Of course, you can easily create a jagged double[][] array of arrays by calling .ToArray():

double[] array = new double[] { 1.0, 2.0, 3.0 };
double[] array1 = new double[] { 4.0, 5.0, 6.0 };

List<double[]> list = new List<double[]>();
list.Add(array);
list.Add(array1);

double[][] jaggedArray = list.ToArray();
0xA3
You also can add trailing zeroes if array isn't of the required size
abatishchev
@abatishchev: Yes, good point. This would require an additional pass to find the maximum length entry in the list first so you can determine the array size needed.
0xA3
Finding the longest array in the list first is better to use list[0].
Danny Chen
@Danny: It's rather better to iterate one time more I think than trim all arrays longer than first
abatishchev
@Danny: `new List<double[]>().Max(a => a.Lenght)`
abatishchev
+2  A: 

Well, you probably can't implement it without loops, but you can make the usage a one-liner :

double[,] array = list.To2DArray();

To2DArray is an extension method implemented as follows:

public static class ExtensionMethods
{
    public static T[,] To2DArray<T>(this IEnumerable<IEnumerable<T>> source)
    {
        var jaggedArray = source.Select(r => r.ToArray()).ToArray();
        int rows = jaggedArray.GetLength(0);
        int columns = jaggedArray.Max(r => r.Length);
        var array = new T[rows, columns];
        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < jaggedArray[i].Length; j++)
            {
                array[i, j] = jaggedArray[i][j];
            }
        }
        return array;
    }
}

Note that it will only work in C# 4, since earlier versions don't support covariance. This variant should work in C# 3 but it is more specific:

public static T[,] To2DArray<T>(this IEnumerable<T[]> source)
{
    var jaggedArray = source.ToArray();
    // same code from here
}
Thomas Levesque
You could use `int rows = source.Count(); int columns = source.Max(r => r.Count());` directly without creating a jagged array first.
0xA3
Yes, but I need the jagged array afterwards to access the data (I could use the ElementAt method but it's wouldn't work for enumerables that can be enumerated only once)
Thomas Levesque
A: 
public static T[,] ToMultidimensional<T>(this T[][] arr, int maxSize)
{
    T[,] md = (T[,])Array.CreateInstance(typeof(double), arr.Length, maxSize);

    for (int i = 0; i < arr.Length; i++)
    for (int j = 0; j < arr[i].Length; j++)
        md[i, j] = arr[i][j];

    return md;
}

var arr = new List<double[]>
{
    new double[] { 1, 2, 3 },
    new double[] { 4, 5 }
}
.ToArray();

var j = arr.ToMultidimensional(arr.Max(a => a.Length));
abatishchev