2011-10-12 4 views
2

J'ai une autre question avec Liste des listes. Encore une fois, j'ai la classe de matrice générique comme ci-dessous.C# Liste des listes question

public class Matrix<T> 
{ 
    List<List<T>> matrix; 

    public Matrix() 
    { 
    matrix = new List<List<T>>(); 
    } 

    public void Add(IEnumerable<T> row) 
    { 
    List<T> newRow = new List<T>(row); 
    matrix.Add(newRow); 
    } 
} 

// Test code 
Matrix<double> matrix = new Matrix<double>();  
matrix.Add(new List<double>() { 0, 0 }); 
matrix.Add(new List<double>() { 16.0, 4.0 }); 

Je lis des lignes de chaînes à partir d'un fichier texte qui contient des valeurs avec le format suivant,

0,5 0,4 0,6 0,1 10,1 11,1 0,5 12,0

Le premier ligne spécifie la taille de la matrice 4x2. La deuxième ligne doit être telle que les 4 premières valeurs soient dans la première colonne de la matrice et les quatre dernières valeurs dans la deuxième colonne. Ceci est dynamique, donc la taille n'est pas fixe.

La lecture des lignes et la délimitation de ces lignes sont triées. Ma question est de savoir comment utiliser la classe Matrix pour stocker ces valeurs. En d'autres termes, comment puis-je faire les éléments d'affilée?

Il doit être fait pour que la matrice ressemblera,

0,5 10,1

0,4 11,1

0,6 0,5

0,1 12,0

Merci à l'avance.

+0

Quel est le problème avec le code que vous avez déjà? Il semble que cela devrait fonctionner? –

+0

La question est autour de la partie ajoutée. Parce que c'est dynamique je ne sais pas comment je peux réaliser la matrice.Ajouter (nouvelle liste () {éléments de ligne}) – nixgadgets

+0

Vous le faites déjà dans le code - voulez-vous ajouter plusieurs lignes en même temps? –

Répondre

1

Si les dimensions de votre matrice vraiment mutable? Une meilleure solution pourrait être de passer ses dimensions à l'intérieur de constructeur et d'affecter tableaux dans la matrice:

public class Matrix<T> 
{ 
    private readonly T[][] _matrix; 

    public Matrix(int rows, int cols) 
    { 
     _matrix = new T[rows][]; 
     for (int r = 0; r < rows; r++) 
      _matrix[r] = new T[cols]; 
    } 

    public T this[int r, int c] 
    { 
     get { return _matrix[r][c]; } 
     set { _matrix[r][c] = value; } 
    } 
} 

Sinon, il le ne besoin d'être mutable, vous pouvez choisir d'allouer « paresseux », comme nécessaire:

public class Matrix<T> 
{ 
    private readonly List<List<T>> _matrix; 

    public Matrix() 
    { 
     _matrix = new List<List<T>>(); 
    } 

    public T this[int r, int c] 
    { 
     get 
     { 
      ResizeIfNeeded(r, c); 
      return _matrix[r][c]; 
     } 
     set 
     { 
      ResizeIfNeeded(r, c); 
      _matrix[r][c] = value; 
     } 
    } 

    private void ResizeIfNeeded(int row, int col) 
    { 
     while (_matrix.Count <= r) 
      _matrix.Add(new List<T>()); 

     var row = _matrix[r]; 
     while (row.Count <= c) 
      row.Add(default(T)); 
    } 
} 

Notez que la deuxième approche peut faire beaucoup d'allocations si vous la remplissez de manière séquentielle.

J'opterais pour la première approche (une matrice de taille fixe), puisque dans la plupart des cas ses dimensions sont déjà connues. Il est le plus rapide à allouer, et il est sûr à utiliser dans une application multithread.

Si vous lisez des valeurs à partir d'un fichier, il est beaucoup plus simple de les paramétrer avec des index que d'instancier une nouvelle liste pour chaque ligne.

+0

Merci beaucoup. Je vois votre point ici! – nixgadgets

+0

@kuzyt: J'ai oublié d'ajouter des accesseurs 'set' dans ma première révision. Je l'ai mis à jour. – Groo

0

Donc, vous voulez un ctor qui prend 2 paramètres, la largeur et les valeurs.

public Matrix(int width, IEnumerable<T> values) 
{ 
    if (values.Count() % width != 0) 
     throw new ArgumentException("values parameter is indivisible by width"); 

    int last = 0; 
    for (int i = width; i <= values.Count(); i += width) 
    { 
     Add(values.Skip(last).Take(width)) 
     last = i; 
    } 

} 
+0

Avez-vous des commentaires à faire avec le déclassement? – Jodrell

1
public void AddRange(IEnumerable<List<T>> rows) 
{ 
    foreach (var row in rows) 
    { 
     Add(row); 
    } 
} 

Puis:

AddRange(new List<double>[] { 
    new List<double> { 0.0, 0.0 }, 
    new List<double> { 16.0, 14.0 } }); 
+0

il semble que vous ayez mal compris ma question parce que je n'ai pas l'exprimer correctement. Le problème est que je ne sais pas ce qui est dans le fichier texte en cours de lecture. par conséquent, la taille de la matrice est dynamique. – nixgadgets

+0

Vous n'avez pas demandé de lire les fichiers, vous avez demandé des listes de listes et comment les ajouter à votre matrice .. la solution que vous avez donnée et j'ai étendu les offres avec des matrices de toute taille, irrégulière si nécessaire .. t face à la lecture soit ..? –