Les listes à 2 dimensions sont-elles possibles en c #?

89

Je voudrais mettre en place une liste multidimensionnelle. Pour référence, je travaille sur un analyseur de playlist.

J'ai un fichier / liste de fichiers, que mon programme enregistre dans une liste standard. Une ligne du fichier dans chaque entrée de liste.

J'analyse ensuite la liste avec des expressions régulières pour trouver des lignes spécifiques. Certaines des données / résultats des lignes doivent être mis dans une nouvelle liste multidimensionnelle ; puisque je ne sais pas combien de résultats / données je vais finir avec, je ne peux pas utiliser un tableau multidimensionnel.

Voici les données que je souhaite insérer:

liste
(
    [0] => Liste
        (
            [0] => ID de piste
            [1] => Nom
            [2] => Artiste
            [3] => Album
            [4] => Nombre de lectures
            [5] => Ignorer le compte

        )
    [1] => Liste
        (
Etc....

Exemple réel:

liste
(
    [0] => Liste
        (
            [0] => 2349
            [1] => Le meilleur moment de votre vie
            [2] => Daft Punk
            [3] => Humain après tout
            [4] => 3
            [5] => 2

        )
    [1] => Liste
        (

Donc oui, mlist [0] [0] obtiendrait TrackID de la chanson 1, mlist [1] [0] de la chanson 2 etc.

Mais j'ai d'énormes problèmes pour créer une liste multidimensionnelle. Jusqu'à présent, je suis venu avec

List<List<string>> matrix = new List<List<string>>();

Mais je n'ai pas vraiment eu beaucoup plus de progrès :(

CasperT
la source

Réponses:

137

Eh bien, vous pouvez certainement utiliser un List<List<string>>où vous écririez ensuite:

List<string> track = new List<string>();
track.Add("2349");
track.Add("The Prime Time of Your Life");
// etc
matrix.Add(track);

Mais pourquoi feriez-vous cela au lieu de créer votre propre classe pour représenter une piste, avec les propriétés Track ID, Name, Artist, Album, Play Count et Skip Count? Alors ayez juste un List<Track>.

Jon Skeet
la source
1
Hmm, honnêtement, je ne sais pas trop comment faire ça! J'ai cherché à mettre en place une classe pour la gestion des listes de lecture uniquement, mais je suppose que c'est une meilleure idée.
CasperT
De plus, ne faudrait-il pas savoir combien de pistes je vais éventuellement créer / stocker?
CasperT
2
Non, car la liste <Track> est toujours dimensionnée dynamiquement. Vous analyseriez les données d'une piste, créeriez une nouvelle instance de Track, l'ajouteriez à la liste <Track> puis analyseriez la suivante, etc.
Jon Skeet
caspert, le List <T> garde une trace de la quantité d'objets qu'il stocke pour vous. Vous pouvez accéder au montant en appelant List <T> .Count
Spoike
3
@CasperT Veuillez faire ce que beaucoup ont suggéré et créer un Trackcours. Il sera beaucoup plus facile de comprendre / maintenir le code. Si vous représentez une piste sous la forme d'une liste de chaînes, les indéces dans lesquelles vous stockez un attribut particulier devront être synchronisées sur toutes les instances où vous essayez d'accéder aux informations de piste. Cela deviendra fastidieux à mettre en œuvre à chaque fois et impossible à déboguer. S'il vous plaît, pour votre propre bien, regardez dans les classes. :)
Alexander Kondratskiy
103

Comme Jon Skeet l'a mentionné, vous pouvez le faire avec un List<Track>. La classe Track ressemblerait à ceci:

public class Track {
    public int TrackID { get; set; }
    public string Name { get; set; }
    public string Artist { get; set; }
    public string Album { get; set; }
    public int PlayCount { get; set; }
    public int SkipCount { get; set; }
}

Et pour créer une liste de pistes comme List<Track>vous le faites simplement:

var trackList = new List<Track>();

L'ajout de pistes peut être aussi simple que ceci:

trackList.add( new Track {
    TrackID = 1234,
    Name = "I'm Gonna Be (500 Miles)",
    Artist = "The Proclaimers",
    Album = "Finest",
    PlayCount = 10,
    SkipCount = 1
});

L'accès aux pistes peut se faire avec l'opérateur d'indexation:

Track firstTrack = trackList[0];

J'espère que cela t'aides.

Spoike
la source
4
Si vous voulez être vraiment averti, Track pourrait également être une structure. ;)
Spoike
3
Pas avec la définition que vous avez donnée ... Les structures devraient avoir une taille d'instance inférieure à 16 octets ...
Ian
@Ian: Hmm. Je n'étais pas au courant de cela. J'ai vérifié rapidement la documentation MSDN pour cela et il s'avère que les structures doivent être inférieures à 16 octets. Merci de l'avoir signalé.
Spoike
14
Ils n'ont pas besoin de l'être, ce n'est qu'une recommandation. Cela n'a pas vraiment d'importance; choisissez struct si vous avez besoin d'une sémantique de valeur, sinon simplement de classe. Si vous ne savez pas, utilisez une classe.
jason
@Spoike: comment utiliser la liste dans une boucle 2 for si vous voulez ajouter les données présentes dans la ligne pendant l'itération à travers la boucle. Par exemple:for(i=0;i< length; i++) { for(j=0;j<length2;j++) {// what should be written here to get the values from a 2d array // to this 2d list } }
Sandeep
35

C'est le moyen le plus simple que j'ai trouvé pour le faire.

List<List<String>> matrix= new List<List<String>>(); //Creates new nested List
matrix.Add(new List<String>()); //Adds new sub List
matrix[0].Add("2349"); //Add values to the sub List at index 0
matrix[0].Add("The Prime of Your Life");
matrix[0].Add("Daft Punk");
matrix[0].Add("Human After All");
matrix[0].Add("3");
matrix[0].Add("2");

Récupérer des valeurs est encore plus simple

string title = matrix[0][1]; //Retrieve value at index 1 from sub List at index 0
Jordan LaPrise
la source
4
Bien que la suggestion précédente concernant une classe Track était la meilleure pour les besoins de l'OP, CETTE solution est la meilleure pour moi pour créer une grille d'objets en deux dimensions. Merci!
CigarDoug
2
Oui, c'est ce que j'ai trouvé être la solution la plus simple et la plus élégante, content d'avoir aidé!
Jordan LaPrise
1
Simple et utile! Je vous remercie!
Dov Miller
12

un autre travail autour duquel j'ai utilisé était ...

List<int []> itemIDs = new List<int[]>();

itemIDs.Add( new int[2] { 101, 202 } );

La bibliothèque sur laquelle je travaille a une structure de classe très formelle et je ne veux pas de contenu supplémentaire pour le privilège d'enregistrer deux entrées «liées».

Cela dépend du programmeur qui n'entre qu'un tableau de 2 éléments, mais comme ce n'est pas un élément commun, je pense que cela fonctionne.

Paul Jamison
la source
2

Vous pouvez également ... faire de cette manière,

List<List<Object>> Parent=new  List<List<Object>>();

List<Object> Child=new List<Object>();
child.Add(2349);
child.Add("Daft Punk");
child.Add("Human");
.
.
Parent.Add(child);

si vous avez besoin d'un autre élément (enfant), créez une nouvelle instance de child,

Child=new List<Object>();
child.Add(2323);
child.Add("asds");
child.Add("jshds");
.
.
Parent.Add(child);
DDK
la source
2

Voici comment créer une liste en 2 dimensions

        // Generating lists in a loop.
        List<List<string>> biglist = new List<List<string>>();

        for(int i = 1; i <= 10; i++)
        {
            List<string> list1 = new List<string>();
            biglist.Add(list1);
        }

        // Populating the lists
        for (int i = 0; i < 10; i++)
        {
            for(int j = 0; j < 10; j++)
            {
                biglist[i].Add((i).ToString() + " " + j.ToString());
            }
        }

        textbox1.Text = biglist[5][9] + "\n";

Soyez conscient du danger d'accéder à un emplacement qui n'est pas peuplé.

Ben
la source
1

J'ai utilisé:

List<List<String>> List1 = new List<List<String>>
var List<int> = new List<int>();
List.add("Test");
List.add("Test2");
List1.add(List);
var List<int> = new List<int>();
List.add("Test3");
List1.add(List);

cela équivaut à:

List1
(
[0] => List2 // List1[0][x]
    (
        [0] => Test  // List[0][0] etc.
        [1] => Test2

    )
[1] => List2
    (
        [0] => Test3
SoIAS
la source
Cela m'est utile! Je vous remercie!
Dov Miller
0

Vous pouvez également utiliser DataTable - vous pouvez définir ensuite le nombre de colonnes et leurs types, puis ajouter des lignes http://www.dotnetperls.com/datatable

Val
la source
Mieux vaut s'en tenir à l' List<Track>approche et utiliser a BindingSource, en ajoutant simplement une DataSource à votre DataGridViewtype Trackpour prendre en charge les classes fortement typées dans le code et une visualisation facile à configurer des pistes dans la vue de la grille de données.
Oliver
D'accord, mais parfois vous ne voulez pas afficher les données instantanément et vous ne voulez pas créer une classe de plus juste pour l'utiliser à un seul endroit, donc je préfère utiliser une solution existante. ... Je voulais juste souligner une autre façon de résoudre ce problème! ;)
Val
0

Voici un petit quelque chose que j'ai fait il y a quelque temps pour un moteur de jeu sur lequel je travaillais. Il a été utilisé comme support de variable d'objet local. Fondamentalement, vous l'utilisez comme une liste normale, mais elle contient la valeur à la position du nom de la chaîne (ou de l'ID). Un peu de modification, et vous aurez votre liste 2D.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GameEngineInterpreter
{
    public class VariableList<T>
    {
        private List<string> list1;
        private List<T> list2;

        /// <summary>
        /// Initialize a new Variable List
        /// </summary>
        public VariableList()
        {
            list1 = new List<string>();
            list2 = new List<T>();
        }

        /// <summary>
        /// Set the value of a variable. If the variable does not exist, then it is created
        /// </summary>
        /// <param name="variable">Name or ID of the variable</param>
        /// <param name="value">The value of the variable</param>
        public void Set(string variable, T value)
        {
            if (!list1.Contains(variable))
            {
                list1.Add(variable);
                list2.Add(value);
            }
            else
            {
                list2[list1.IndexOf(variable)] = value;
            }
        }

        /// <summary>
        /// Remove the variable if it exists
        /// </summary>
        /// <param name="variable">Name or ID of the variable</param>
        public void Remove(string variable)
        {
            if (list1.Contains(variable))
            {
                list2.RemoveAt(list1.IndexOf(variable));
                list1.RemoveAt(list1.IndexOf(variable));
            }
        }

        /// <summary>
        /// Clears the variable list
        /// </summary>
        public void Clear()
        {
            list1.Clear();
            list2.Clear();
        }

        /// <summary>
        /// Get the value of the variable if it exists
        /// </summary>
        /// <param name="variable">Name or ID of the variable</param>
        /// <returns>Value</returns>
        public T Get(string variable)
        {
            if (list1.Contains(variable))
            {
                return (list2[list1.IndexOf(variable)]);
            }
            else
            {
                return default(T);
            }
        }

        /// <summary>
        /// Get a string list of all the variables 
        /// </summary>
        /// <returns>List string</string></returns>
        public List<string> GetList()
        {
            return (list1);
        }
    }
}
Joe Horrell
la source