Hallo zusammen,
ich hänge gerade bei einem Problem etwas in der Luft und hoffe ihr könnt mir helfen.
// Eine Liste mit vielen Zeilen die wiederum pro Zeile mehrere Spalten enthält
List<List<string>> lines = new List<List<string>>();
// In der Liste steht z.B.
// 1. Zeile: A, B, C
// 2. Zeile: A, B, D
// 3. Zeile: A, C, E
// Wieviel Spalten eine Zeile hat ist unbekannt.
// Ich möchte nun gruppieren das am ende die folgende Struktur heraus kommt:
//
// A, B, C
// , , D
// A, C, E
// Also quasi eine Gruppierung nach einer unbekannten Anzahl an spalten, damit Werte nicht doppelt übereinander stehen.
Hat jemand eine Idee?
Noch ein Beispiel:
Welt, Europa, Deutschland
Welt, Europa, England,
Welt, Europa, Frankreich
wird in der Ausgabe zu
Welt, Europa, Deutschland
England
Frankreich
Vielleicht bietet sich auch eine andere Struktur an.
Danke und viele Grüße,
Sythus
Hi,
schau doch einfach nach ob ein Vorgänger existiert und dieser denselben Wert hat.
Möchtest du die äußere Liste sortieren (quasi alphabetisch bzw. wie ein Inhaltsverzeichnis) und dann so ausgeben, dass jeweils nur die sich unterscheidenden Elemente mit entsprechender Einrückung dargestellt werden ?
a b c d (abcd)
e f (abcdef)
g h i (abghi)
j k (abgjk)
Dafür müsste jedes Zeilen-Element über seine Vorgänger Bescheid wissen. Also vor der Ausgabe prüfen, wieviele Elemente zu Beginn übereinstimmen.
Ob eine einfache List<string> da das Mittel der Wahl ist, würde ich mir noch einmal überlegen.
LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Ob eine einfache List<string> da das Mittel der Wahl ist, würde ich mir noch einmal überlegen.
Nach den Anforderungen zu urteilen, wird hier wohl eher eine hierarchische Datenstruktur benötigt:
public class Node
{
public string Name { get; set; }
public Node ParentNode { get; set; }
public List<Node> ChildNodes { get; set; }
}
Christian
Weeks of programming can save you hours of planning
Decorator reicht.
LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Hallo und vielen Dank für Eure Rückmeldungen.
Das mit der Node Struktur gefällt mir gut.. aber ich habe ehrlich gesagt das Problem diese ordentlich zu füllen
Die Daten kommen Beispielsweise so:
Welt, Europa, Deutschland
Welt, Europa, England
Welt, Europa, Frankreich
Ich bräuchte folgende Struktur.
Node.Name = Welt
{
Node.Name = Europa
{
Node.Name = Deutschland
Node.Name = England
Node.Name = Frankreich
}
}
Kann mich da jemand in die richtige Richtung schieben?
Danke 😃
Die Struktur sollte beliebig tief sein können.
Dann bräuchtest du eine Zuordnung, um einen bereits existierenden Knoten anhand dessen Namen wiederzufinden, z.B. mit einem Dictionary<string, Node>
.
Mit der TryGetValue(string, out Node)-Methode kannst du bereits bestehende Knoten finden bzw. herausfinden, ob es noch keinen Knoten gibt. Wenn es auf mehreren Ebenen Knoten mit dem gleichen Namen gibt (z.B. Welt - Australien - Australien), dann mußt du die Knoten für alle drei Ebenen getrennt verwalten.
Christian
// Edit:
Noch eleganter fände ich allerdings eine Umsetzung mit Linq. Man könnte z.B. die GroupBy-Methode verwenden, um die Hierarchie abzubilden. Das sieht dann etwa so aus:
// Testdaten
var countries = new List<string>()
{
"Welt,Europa,Deutschland",
"Welt,Europa,England",
"Welt,Europa,Frankreich",
"Welt,Australien,Australien"
};
// Konvertierung
Node worldNode = countries
.Select(m => m.Split(','))
.GroupBy(m => new { Continent = m[1], Planet = m[0] } ) // Nach Erdteil gruppieren
.GroupBy(m => m.Key.Planet) // Nach "Planet" gruppieren => "Welt"-Knoten
.Select(m => new Node() // In Hierarchie konvertieren
{
Name = m.Key, // "Planet"
ChildNodes = m.Select(n => new Node()
{
Name = n.Key.Continent, // Erdteil
ChildNodes = n.Select(o => new Node()
{
Name = o[2], // Land
ChildNodes = null
}).ToList()
}).ToList()
})
.Single(); // "Welt"-Knoten auswählen
In dem Beispiel verzichte ich auf die Node.Parent-Eigenschaft. Wenn diese im Programm benötigt wird, muß man sie noch irgendwie (möglichst elegant) setzen.
Weeks of programming can save you hours of planning
Hi Christian,
danke für deine Antwort.
das funktioniert gut, so lange man die Menge der Einträge kennt. Die Struktur innerhalb ist aber unbekannt, auch die Tiefe.
Ich versuche es aber mal in die Richtung weiter 😃
DAnke und VG
Wie gesagt, Decorator. Grob gesagt eine Objekthierarchie, die Verweise auf vorangehende Objekte derselben Klasse enthalten. Damit sollte das ganze sehr schmerzfrei in beliebiger Tiefe gehen. Google mal danach und schau dir ein paar Beispiele an.
LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Das sollte für beliebige zweidimensionale Arrays funktionieren:
void test()
{
controlBreak(
new string[,]
{
{"A", "B", "C"},
{"A", "C", "D"},
{"B", "B", "D"},
{"B", "A", "B"},
{"B", "A", "C"},
{"B", "A", "D"}
});
controlBreak(
new string[,]
{
{"A", "B", "C", "1"},
{"A", "B", "D", "2"},
{"A", "B", "D", "3"},
{"A", "C", "F", "1"},
{"B", "C", "F", "1"},
{"B", "C", "D", "1"}
});
}
static void controlBreak(string[,] array)
{
for (int rowIndex = 0; rowIndex < array.GetLength(0); rowIndex++)
{
bool b = true;
for (int colIndex = 0; colIndex < array.GetLength(1); colIndex++)
{
if (rowIndex == 0 || !b || array[rowIndex - 1, colIndex] != array[rowIndex, colIndex])
{
Debug.Print(new string('-', colIndex) + array[rowIndex, colIndex]);
if (rowIndex != 0)
b = false;
}
}
}
}
Das sollte für beliebige zweidimensionale Arrays funktionieren
Aber nur, wenn sie schon in der richtigen Reihenfolge sortiert sind.
Christian
Weeks of programming can save you hours of planning