Cómo convertir una lista de matrices en una matriz multidimensional

Necesito convertir la siguiente colección en doble [,]:

var ret = new List(); 

Todas las matrices de la lista tienen la misma longitud. El enfoque más simple, ret.ToArray() , produce double [] [], que no es lo que quiero. Por supuesto, puedo crear una nueva matriz manualmente y copiar números en un bucle, pero ¿hay una manera más elegante?

Editar: mi biblioteca se invoca desde un idioma diferente, Mathematica, que no se ha desarrollado en .Net. No creo que el lenguaje pueda utilizar arreglos dentados. Tengo que devolver una matriz multidimensional.

No creo que haya nada incorporado en el marco para hacer esto, incluso Array.Copy falla en este caso. Sin embargo, es fácil escribir el código para hacerlo mediante un bucle:

 using System; using System.Collections.Generic; class Test { static void Main() { List list = new List { new[] { 1, 2, 3 }, new[] { 4, 5, 6 }, }; int[,] array = CreateRectangularArray(list); foreach (int x in array) { Console.WriteLine(x); // 1, 2, 3, 4, 5, 6 } Console.WriteLine(array[1, 2]); // 6 } static T[,] CreateRectangularArray(IList arrays) { // TODO: Validation and special-casing for arrays.Count == 0 int minorLength = arrays[0].Length; T[,] ret = new T[arrays.Count, minorLength]; for (int i = 0; i < arrays.Count; i++) { var array = arrays[i]; if (array.Length != minorLength) { throw new ArgumentException ("All arrays must be the same length"); } for (int j = 0; j < minorLength; j++) { ret[i, j] = array[j]; } } return ret; } } 

Puede hacer lo siguiente como extensión:

  ///  /// Conerts source to 2D array. ///  ///  /// The type of item that must exist in the source. ///  ///  /// The source to convert. ///  ///  /// Thrown if source is null. ///  ///  /// The 2D array of source items. ///  public static T[,] To2DArray(this IList> source) { if (source == null) { throw new ArgumentNullException("source"); } int max = source.Select(l => l).Max(l => l.Count()); var result = new T[source.Count, max]; for (int i = 0; i < source.Count; i++) { for (int j = 0; j < source[i].Count(); j++) { result[i, j] = source[i][j]; } } return result; } 

No hay una manera fácil de hacerlo porque, en la situación que describes, no hay nada que impida que las matrices double[] de la lista sean de diferentes tamaños, lo que sería incompatible con una matriz rectangular bidimensional. Sin embargo, si está en la posición de garantizar que las matrices double[] tienen la misma dimensionalidad, puede construir su matriz bidimensional de la siguiente manera:

 var arr = new double[ret.Count(),ret[0].Count()]; for( int i=0; i 

Esto producirá un error de tiempo de ejecución si cualquiera de las matrices double[] en la lista es más corta que la primera, y perderá datos si cualquiera de las matrices es más grande que la primera.

Si realmente está decidido a almacenar una matriz dentada en una matriz rectangular, puede usar un valor "mágico" para indicar que no hay ningún valor en esa posición. Por ejemplo:

 var arr = new double[ret.Count(),ret.Max(x=>x.Count())]; for( int i=0; i 

En una nota editorial, creo que esta es una idea muy mala ™; Cuando vaya a utilizar la matriz rectangular, debe verificar Double.NaN todo el tiempo. Además, ¿qué Double.NaN si quisiera utilizar Double.NaN como un valor legítimo en la matriz? Si tienes una matriz dentada, solo debes dejarla como una matriz dentada.

Si vas a copiar (no puedo pensar en una mejor manera)

 var width = ret[0].length; var length = ret.Count; var newResult = new double[width, length] Buffer.BlockCopy(ret.SelectMany(r => r).ToArray(), 0, newResult, 0, length * width); return newResult; 

EDITAR

Estoy casi seguro de bucle en lugar de usar SelectMany y ToArray es más rápido.

Sé cuando he sido engañado.

Intereting Posts