Sind zweidimensionale Listen in c # möglich?

88

Ich möchte eine mehrdimensionale Liste erstellen. Als Referenz arbeite ich an einem Playlist-Analysator.

Ich habe eine Datei / Dateiliste, die mein Programm in einer Standardliste speichert. Eine Zeile aus der Datei in jedem Listeneintrag.

Ich analysiere dann die Liste mit regulären Ausdrücken, um bestimmte Zeilen zu finden. Einige der Daten / Ergebnisse aus den Zeilen müssen in eine neue mehrdimensionale Liste aufgenommen werden. Da ich nicht weiß, mit wie vielen Ergebnissen / Daten ich enden werde, kann ich kein mehrdimensionales Array verwenden.

Hier sind die Daten, die ich einfügen möchte:

Aufführen
(
    [0] => Liste
        (
            [0] => Track ID
            [1] => Name
            [2] => Künstler
            [3] => Album
            [4] => Anzahl spielen
            [5] => Anzahl überspringen

        )
    [1] => Liste
        (
Und so weiter....

Echtes Beispiel:

Aufführen
(
    [0] => Liste
        (
            [0] => 2349
            [1] => Die Hauptzeit deines Lebens
            [2] => Daft Punk
            [3] => Immerhin ein Mensch
            [4] => 3
            [5] => 2

        )
    [1] => Liste
        (

Also ja, mlist [0] [0] würde TrackID von Song 1, mlist [1] [0] von Song 2 usw. erhalten.

Aber ich habe große Probleme beim Erstellen einer mehrdimensionalen Liste. Bisher habe ich mir ausgedacht

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

Aber ich habe nicht wirklich viel mehr Fortschritte gemacht :(

CasperT
quelle

Antworten:

137

Nun haben Sie sicher kann verwenden ein List<List<string>>, man würde dann schreiben:

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

Aber warum sollten Sie das tun, anstatt eine eigene Klasse zu erstellen, die einen Titel mit den Eigenschaften Titel-ID, Name, Künstler, Album, Wiedergabezahl und Überspringzahl darstellt? Dann haben Sie einfach eine List<Track>.

Jon Skeet
quelle
1
Hmm, ich bin mir ehrlich gesagt nicht sicher, wie ich das machen soll! Ich habe mir überlegt, eine Klasse für die Bearbeitung von Wiedergabelisten einzurichten, aber ich denke, das ist eine bessere Idee.
CasperT
Wäre es nicht erforderlich zu wissen, wie viele Tracks ich irgendwann erstellen / speichern werde?
CasperT
2
Nein, da die Liste <Track> immer noch dynamisch dimensioniert ist. Sie würden die Daten für eine Spur analysieren, eine neue Instanz von Spur erstellen, sie zur Liste <Track> hinzufügen und dann die nächste analysieren usw.
Jon Skeet
caspert, die Liste <T> verfolgt die Anzahl der Objekte, die für Sie gespeichert werden. Sie können auf den Betrag zugreifen, indem Sie List <T> .Count
Spoike
3
@CasperT Bitte mach was viele vorgeschlagen haben und mache eine TrackKlasse. Es wird viel einfacher sein, den Code zu verstehen / zu pflegen. Wenn Sie eine Spur als Liste von Zeichenfolgen darstellen, müssen die Unabhängigkeiten, in denen Sie ein bestimmtes Attribut speichern, über alle Instanzen hinweg synchronisiert werden, in denen Sie versuchen, auf Spurinformationen zuzugreifen. Die Implementierung wird jedes Mal mühsam und das Debuggen unmöglich. Bitte schauen Sie sich um Ihrer selbst willen den Unterricht an. :)
Alexander Kondratskiy
103

Wie Jon Skeet bereits erwähnt hat, können Sie dies List<Track>stattdessen mit einem tun . Die Track-Klasse würde ungefähr so ​​aussehen:

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

Und um eine Titelliste zu erstellen, List<Track>tun Sie einfach Folgendes:

var trackList = new List<Track>();

Das Hinzufügen von Tracks kann so einfach sein:

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

Der Zugriff auf Tracks kann mit dem Indexierungsoperator erfolgen:

Track firstTrack = trackList[0];

Hoffe das hilft.

Spoike
quelle
4
Wenn Sie wirklich versiert sein möchten, kann Track auch eine Struktur sein. ;)
Spoike
3
Nicht mit der Definition, die Sie gegeben haben ... Strukturen sollten eine Instanzgröße von weniger als 16 Byte haben ...
Ian
@ Ian: Hmm. Das war mir nicht bewusst. Schnell überprüftes MSDN-Dokument dafür und es stellt sich heraus, dass Strukturen weniger als 16 Bytes haben müssen. Vielen Dank für den Hinweis.
Spoike
14
Sie nicht brauchen zu sein, es ist nur eine Empfehlung. Es ist nicht wirklich wichtig; Wählen Sie struct, wenn Sie eine Wertesemantik benötigen, andernfalls nur class. Wenn Sie es nicht wissen, verwenden Sie eine Klasse.
Jason
@Spoike: Verwendung der Liste innerhalb einer 2 für Schleifen, wenn Sie die in einer Zeile vorhandenen Daten hinzufügen möchten, während Sie die Schleife durchlaufen. Zum Beispiel: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

Dies ist der einfachste Weg, den ich gefunden habe, um es zu tun.

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");

Das Abrufen von Werten ist noch einfacher

string title = matrix[0][1]; //Retrieve value at index 1 from sub List at index 0
Jordan LaPrise
quelle
4
Obwohl der frühere Vorschlag für eine Track-Klasse am besten für die Anforderungen des OP geeignet war, ist DIESE Lösung für mich die beste, um ein zweidimensionales Raster von Objekten zu erstellen. Vielen Dank!
CigarDoug
2
Ja, das ist die einfachste und eleganteste Lösung, ich bin froh, dass ich geholfen habe!
Jordan LaPrise
1
Einfach und hilfreich! Danke dir!
Dov Miller
12

Eine andere Arbeit, die ich verwendet habe, war ...

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

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

Die Bibliothek, an der ich arbeite, hat eine sehr formale Klassenstruktur und ich wollte dort keine zusätzlichen Dinge für das Privileg, zwei "verwandte" Ints aufzunehmen.

Verlässt sich darauf, dass der Programmierer nur ein Array mit 2 Elementen eingibt, aber da es kein allgemeines Element ist, denke ich, dass es funktioniert.

Paul Jamison
quelle
2

Sie können auch ... auf diese Weise tun,

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

Wenn Sie ein anderes Element (untergeordnetes Element) benötigen, erstellen Sie eine neue Instanz von untergeordnetem Element.

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

Hier erfahren Sie, wie Sie eine zweidimensionale Liste erstellen

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

Seien Sie sich der Gefahr bewusst, auf einen Ort zuzugreifen, der nicht besiedelt ist.

Ben
quelle
1

Ich benutzte:

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

das entspricht:

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

    )
[1] => List2
    (
        [0] => Test3
SoIAS
quelle
Das ist hilfreich für mich! Danke dir!
Dov Miller
0

Sie können auch DataTable verwenden - Sie können dann die Anzahl der Spalten und ihre Typen definieren und dann Zeilen hinzufügen http://www.dotnetperls.com/datatable

Val
quelle
Halten Sie sich besser an den List<Track>Ansatz und verwenden Sie a BindingSource, indem Sie einfach eine DataSource zu Ihrem DataGridViewTyp hinzufügen Track, um stark typisierte Klassen im Code zu unterstützen und die Visualisierung der Spuren in der Datenrasteransicht einfach zu konfigurieren.
Oliver
Einverstanden, aber manchmal möchten Sie die Daten nicht sofort anzeigen und keine weitere Klasse erstellen, um sie nur an einem Ort zu verwenden. Daher bevorzuge ich die Verwendung einer vorhandenen Lösung. ... wollte nur einen weiteren Weg aufzeigen, um dies zu lösen! ;)
Val
0

Hier ist etwas, das ich vor einiger Zeit für eine Spiel-Engine gemacht habe, an der ich gearbeitet habe. Es wurde als lokaler Objektvariablenhalter verwendet. Grundsätzlich verwenden Sie es als normale Liste, aber es enthält den Wert an der Position des Zeichenfolgennamens (oder der ID). Ein bisschen Modifikation, und Sie haben Ihre 2D-Liste.

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
quelle