Come convertire la lista di array in una matrice multidimensionale

Devo convertire la seguente collezione in double [,]:

var ret = new List(); 

Tutti gli array nell’elenco hanno la stessa lunghezza. L’approccio più semplice, ret.ToArray() , produce double [] [], che non è quello che voglio. Naturalmente, posso creare manualmente un nuovo array e copiare i numeri in un ciclo, ma esiste un modo più elegante?

Modifica: la mia libreria è invocata da una lingua diversa, Mathematica, che non è stata sviluppata in .Net. Non credo che la lingua possa utilizzare array frastagliati. Devo restituire un array multidimensionale.

Non credo che ci sia qualcosa di costruito nel framework per farlo, anche in questo caso Array.Copy fallisce. Tuttavia, è facile scrivere il codice per farlo in loop:

 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; } } 

Puoi seguire come estensione:

  ///  /// 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; } 

Non c’è un modo semplice per farlo perché nella situazione che stai descrivendo, non c’è nulla che impedisca ai double[] array della lista di essere di dimensioni diverse, il che sarebbe incompatibile con una matrice rettangular bidimensionale. Tuttavia, se sei nella posizione di garantire che gli array double[] abbiano tutti la stessa dimensionalità, puoi build il tuo array bidimensionale come segue:

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

Questo produrrà un errore di run-time se uno qualsiasi dei double[] array double[] nella lista è più corto del primo, e perderai i dati se uno degli array è più grande del primo.

Se si è veramente determinati a memorizzare una matrice seghettata in una matrice rettangular, è ansible utilizzare un valore "magico" per indicare che non vi è alcun valore in quella posizione. Per esempio:

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

In una nota redazionale, penso che questa sia un'idea molto ctriggers; quando si usa l'array rettangular, è necessario verificare Double.NaN per tutto il tempo. Inoltre, cosa succede se si desidera utilizzare Double.NaN come valore legittimo nell'array? Se hai una matrice seghettata, dovresti lasciarla come una matrice seghettata.

Se hai intenzione di copiare (non riesco a pensare a un modo migliore)

 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; 

MODIFICARE

Sono quasi certo che il ciclo invece di usare SelectMany e ToArray sia più veloce.

So quando sono stato ammantato.