recorrer multidimensional matriz llenar examples dinamico bidimensional arreglos arreglo array 3x3 c# linq multidimensional-array jagged-arrays

c# - llenar - Cómo convertir la lista de matrices en una matriz multidimensional



multidimensional array c# examples (4)

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

using System; using System.Collections.Generic; class Test { static void Main() { List<int[]> list = new List<int[]> { 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<T>(IList<T[]> 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; } }

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

var ret = new List<double[]>();

Todos los arreglos en la lista tienen la misma longitud. El enfoque más simple, ret.ToArray() , produce el doble [] [], que no es lo que quiero. Por supuesto, puedo crear una nueva matriz manualmente y copiar los números en un bucle, pero ¿hay una forma más elegante?

Edición: mi biblioteca se invoca desde un lenguaje diferente, Mathematica, que no se ha desarrollado en .Net. No creo que el lenguaje pueda utilizar matrices irregulares. Tengo que devolver una matriz multidimensional.


No hay una manera fácil de hacer esto porque en la situación que está describiendo, no hay nada que impida que las matrices double[] en la lista tengan 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[] tengan 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<ret.Count(); i++ ) { for( int j=0; j<ret[i].Count(); j++ ) arr[i,j] = ret[i][j]; }

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 alguna de las matrices es más grande que la primera.

Si realmente está decidido a almacenar una matriz irregular 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<ret.Count(); i++ ) { for( int j=0; j<arr.GetLength(1); j++ ) arr[i,j] = j<ret[i].Count() ? ret[i][j] : Double.NaN; }

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 usar Double.NaN como un valor legítimo en la matriz? Si tiene una matriz irregular, debe dejarla como una matriz irregular.


Puedes hacer lo siguiente como extensión:

/// <summary> /// Conerts source to 2D array. /// </summary> /// <typeparam name="T"> /// The type of item that must exist in the source. /// </typeparam> /// <param name="source"> /// The source to convert. /// </param> /// <exception cref="ArgumentNullException"> /// Thrown if source is null. /// </exception> /// <returns> /// The 2D array of source items. /// </returns> public static T[,] To2DArray<T>(this IList<IList<T>> 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; }


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 que el bucle en lugar de utilizar SelectMany y ToArray es más rápido.

Sé cuando he sido skeeted.