VisualBasic list (of String) sortieren

Gilrich

Cadet 4th Year
Registriert
Nov. 2009
Beiträge
96
Hallo

Ich habe in meinem Programm eine List (of String). Diese möchte ich nun zufällig sortieren.
Das heisst so, dass sie einzelnen Strings eine beliebige Reihenfolge haben.
Ich hab mir schon die List(T).sort Methode angesehn. Das hat mir aber nicht weitergeholfen.
Ich wäre sehr dankbar, wenn mir jemand helfen könnte.

Gruss Gilrich

Sprache: VB.net
 
Sortieren heißt nunmal das die Elemente der Liste eine bestimmte Reihenfolge haben die anhand eines bestimmten Vergleichkriteriums erfolgt. Also was wäre das für ein Kriterium in deinem Fall. Zufall ist nicht wirklich ein Kriterium nach dem man sortieren kann. Ich würde mal vermuten, dass du eine Art Jukebox machst, die eine Liste von Songs produziert, deren Reihenfolge zufällig ist. Also wenn du schon eine generische Liste hast, dann mach doch noch eine 2. Liste (ebenfalls List(Of String)). Über die .Net Random Klasse kannst du dann mehr oder wenige gute Zufallszahlen erzeugen:

Code:
Dim listSource As List(Of String)
listSource.Add("ABC")
listSource.Add("DEF")
listSource.Add("GHI")
listSource.Add("JKL")
listSource.Add("MNO")
listSource.Add("PQR")

Dim listTarget As New List(Of String)(listSource.Count)
Dim randomize As New System.Random()
While (listSource.Count > 0)
  Dim index As Integer = randomize.Next(listSource.Count - 1)
  listTarget.Add(listSource(index))
End While

listSource ist deine Liste die du schon hast, listTarget ist die Liste von der ich spreche. Diese wird dann die zufälligen Einträge enthalten. Der Rest dürfte dann relativ einfach sein.

Vie Erfolg
 
@Rossibaer

In deinem Code sind sowohl syntaktische, als auch logische Fehler.

1)
Code:
listTarget.Add(listSource[B][COLOR="Red"]([/COLOR][/B]index[B][COLOR="Red"])[/COLOR][/B])
Das müssen eckige Klammern sein, du willst ja auf den Indexer zugreifen.

2)
Code:
randomize.Next(listSource.Count - 1)
Die Obergrenze die du an die Methode übergibst wird ausgeschlossen
--> das letzte Element der Liste wird auch immer das letzte Element bleiben
Einfach das -1 weglassen, dann stimmts.

3) Du hast ne Endlosschleife gebastelt. listScource.Count wird immer gleich bleiben, da aus der Liste nix entfernt wird.
Da fehlt das listTarget.RemoveAt(index);


@TS
Die schönste Lösung wäre per Erweiterungsmethode (siehe hier, die beste Antwort von Strilanc)

Ist zwar C# aber du kannst es ja in VB umwandlen lassen: klick

Ist dann recht einfach anzuwenden:
Code:
Dim list As New List(Of String)()

'Strings zur Liste hinzufügen...

'Mischen
list = list.Shuffle(New Random()).ToList()
 
Zuletzt bearbeitet:
@Grantig: Danke für deine Verbesserungsvorschläge:

1. müssen eckige Klammern sein, du willst ja auf den Indexer zugreifen.
Das ist der Unterschied zwischen C# und VB, VB kennt die eckigen Klammern bei einem Indexer nicht, während C# eckige Klammern verwendet. Lies mal in der Doku nach...

zu 2. ok, habe das Ganze mal aus dem Bauch getippt ohne vorher genau in der Doku nach zu lesen, ist aber für den Zweck nicht gerade der Superbug, mea culpa.

zu 3.
Der Rest dürfte dann relativ einfach sein.
Soll heißen. Schau ob du was damit anfangen kannst und passe es an deine Bedürfnisse an. Das ganze war nur ein Prototyp, spätestens beim Debuggen wäre das Problem ersichtlich gewesen, wenn es denn überhaupt eins darstellt. Weder du noch ich wissen, wie die Ausgabeliste aussehen soll oder was passieren soll. Es war nicht bekannt ob der TE die Liste nur so groß machen will, wie die Eingabeliste oder ob kontinuierlich eine zufällige Liste generiert werden soll. Dann wäre die Abbruchbedingung eben nicht die Anzahl der Einträge in der Eingabeliste sondern vielleicht das Drücken einer Tastenkombination oder ähnliches. Mir ist auch klar, das hier noch das Entfernen der Elemente aus der Eingabeliste notwendig wäre. Aber wofür gibt es Debugger?

Und allgemein kann ich nur sagen "schön" liegt im Auge des Betrachters. Für mich ist etwas schön wenn es kurz und knackig ist. Und da sind nunmal 7 Zeilen (von mir) gegen die 7 Zeilen deiner Quelle nun wirklich alles andere als häßlich. Ebenso hat dein Codebeispiel einen in meinen Augen schlechten Stil: Exceptions zur Ablaufsteuerung ist wirklich beschissen, wenn der aufrufende Code, diese nicht behandelt. Oder wer will schon ein Programm, dass bei einem kleinen Fehler (leere Liste wird übergeben) gleich vollständig beendet wird? Einzig schön ist, das diese Lösung inplace arbeitet und somit nicht 2 Listen gehalten werden.

Hier noch mein "fehlerbereinigter" Code
Code:
Dim listTarget As New List(Of String)(listSource.Count)
Dim randomize As New System.Random()
While (listSource.Count > 0)
  Dim index As Integer = randomize.Next(listSource.Count)
  listTarget.Add(listSource(index))
  listSource.RemoveAt(index)
End While
 
Zuletzt bearbeitet:
Hab das jetzt geschafft
Vielen Dank euch beiden!

Gruss Gilrich
 
@Rossibaer

zu 1) Tja, klugscheißen will gelernt sein ;)
Da hab ich ja mal mächtig ins Klo gegriffen, von VB hab ich einfach zu wenig Ahnung, mir ist das einfach ins Auge gesprungen, weils eben in C# anders ist. Sorry dafür. :(

zu 2) Naja, das kann schon nervig werden und der Fehler ist auch nicht leicht zu finden, wenn man nicht weiß wo er liegt. Genau dieser Fehler hat mir schonmal ziemliche Kopfschmerzen bereitet.

zu 3) Im Sinne von OOP finde ich es schöner ne Erweiterungsmethode zu benutzen.
Imo sieht der Code mit Erweiterungsmethode deutlich aufgeräumter aus.
Außerdem wird dadurch Redundanz verhindert, falls der TS öfter als nur einmal in seinem Code ne Liste mischen will.

Zu den Exceptions:
Der Caller muss den check gegen null schon selbst durchführen. Wenn die Methode den Fehler einfach "verschlucken" und ne leere Liste zurückgeben würde, dann weiß der Caller nicht, ob die Rückgabe jetzt leer ist, weil die Quellliste leer ist, oder weil die Quelliste null ist.
Vor allem wenn jemand anders den Code falsch verwendet, kann das zu Bugs führen, da der Caller beim testen nicht darauf aufmerksam gemacht wird, dass was schiefgelaufen ist.

Btw auch MS selbst sieht das so (siehe hier)
 
siehe 1) und 2) ... und jeder macht mal Fehler ;)

zu 3) jetzt hast du mich auf ein neues Sprachfeature von .Net 3.x und höher aufmerksam gemacht, das ich gleich in meine "Don't Try" Liste aufnehmen werde, weil sich mir der Magen umdreht, dass ein Stück Code ausserhalb einer Klasse existieren kann, der die Klasse bzw. deren Möglichkeiten zum Guten oder Schlechten erweitert. Ist das wirklich noch im Sinne des OOP?

Zu den Exceptions: Da scheiden sich die Geister. Mir ist robuster Code lieber als Code der bei kleinen Fehlern zum fatalen Absturz des Programms führt. Ebenso ist es in einer Firma nicht immer möglich alle Programmierer so zu trainieren, das diese die Methoden auch richtig anwenden. Es bedarf dann "Experten" Wissen wie in welcher Form die Klassen/Objekte/Methoden/Eigenschaften ... verwendet werden. Ebenso zeigen sich diese Fehler nicht beim Kompilieren sondern erst zur Laufzeit.

Und nun zur 1 Million Euro Frage: Warum muss ein Programm abstürzen, wenn die Quellliste leer ist ? Wenn die Quellliste leer ist, sollte doch wohl eher das Programm weiterlaufen können oder? Bei den Exceptions sehe ich dann aber zig fach redundanten Code die die Ausnahmen abfangen bzw. Rahmenbedingungen prüfen. Und das in größeren Projekten mit mehreren Entwicklern mehr schlecht als recht. Was ist, wenn die Fehlerbehandlung ebenfalls Fehler hat, da denke ich nur an FIAT (Fix it again Tony!) Am Ende führt es doch wohl eher dazu, das in jedem Stück Code ein Try Catch landet. Der Code wird immer größer. Möglichst auch noch geschachtelte Try Catch Blöcke drin. Dann besteht das Programm aus mehr Fehlerbehandlung als aktiver Code, der wirklich was macht...

Aber da kann jeder seine eigene Meinung haben oder sich bilden.

Gut finde ich jedoch den Gedankenaustausch mit Grantig und das Gilrich sein Problem nun lösen konnte. Also Ziel erreicht, der nächste bitte... ;)
 
Zurück
Oben