String zerlegen

  • VB.NET

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von Koopakiller.

    String zerlegen

    Hallo Zusammen
    Ich habe folgende Herausforderung, vielleicht habt ihr mir einen Tipp.
    In einer Textdatei sind Wörter mit Klammern enthalten, z.B. Zürich (CH) oder München (DE)

    Ich möchte die Wörter auslesen, aber ohne die Klammern und deren Inhalt, also nur Zürich oder München.
    WICHTIG: Es kann auch sein, dass die Klammern am Anfang stehen oder mitten in einer Zeile.
    Wie würdet ihr das lösen? Mir fällt keine Funktion ein um dies zu bewerkstelligen.

    Gruss und danke, reustli
    Hallo, kommt erstmal ganz darauf an, wie die Wörter voneinander getrennt sind. Ich nehme mal an das sie durch Semikolons getrennt sind. Dann würde ich erstmal den Inhalt einlesen und an den Semikolons aufsplitten:

    VB.NET-Quellcode

    1. Dim items As String() = File.ReadAllText("C:\MYFILE.txt").Split(";"C)


    Nun würde ich alle Zeilen durchgehen und über ein paar String-Zeichen-Such-Operationen die Klammern entfernen:

    VB.NET-Quellcode

    1. For i As Integer = 0 To items.Length - 1
    2. Dim b1 As Integer = items(i).IndexOf("("C)
    3. 'Index der öffnenden Klammer
    4. Dim b2 As Integer = items(i).IndexOf(")"C)
    5. 'Index der Schließenden Klammer
    6. 'Klammern mit Inhalt entfernen
    7. items(i) = items(i).Remove(b1, b2 - b1)
    8. Next


    Dann enthält das Array items alle Städte (oder was auch immer) ohne den Länderkürzeln.
    Ich habe den Code nicht getestet, er sollte aber die Funktionsweise zeigen.
    @xtts02
    Regex ist zwar praktisch, aber mithilfe von zweimal IndexOf ist alles erledigt. Als ich die Antwort geschrieben habe dachte ich auch erst an Regex, jedoch fand ich IndexOf als Leistungssparender. Ohne es zu testen könnte der Regex so aussehen:

    Quellcode

    1. \(\w+\)

    Alle Funde müssen dann durch string.Empty ersetzt werden. Regex hat hier den Vorteil, das alle Vorkommen auf einmal ersetzt werden können.
    Danke für eure Antworten, das mit dem Index der ersten Klammer und der letzten ist - meines Erachtens - ein guter Ansatz. Ich werde das versuchen. Nachfolgend zwei Zeilen aus dem Textfile, es handelt sich um Synonyme:

    Quellcode

    1. bombastisch;übermässig;üppig;gepfeffert (umgangssprachlich);horrend
    2. präoperativ (fachsprachlich);vor der Operation


    Noch kurz eine ganz andere Frage, weshalb machst du bei der Split Funktion noch ein C hinten dran?
    Das mit dem c ist einfach so eine Angewohnheit. Ich habe ursprünglich mit C# angefangen bin mache das auch weiterhin. VB gelernt habe ich mit Konvertern, die alle ein c dran hängen wenn ein Char und kein String gefordert ist.

    Da die Klammern mitten in einer Zeile stehen können, was ich mir auch dachte, ist IndexOf besser geeignet als Regex, da ein Regex hier relativ komplex wäre.
    Eine andere Aternative wäre String.Split

    VB.NET-Quellcode

    1. Dim input As String = "bombastisch;übermässig;üppig;gepfeffert (umgangssprachlich);horrend"
    2. Dim result As New List(Of String)
    3. For Each block In input.Split(";"c)
    4. Dim part = block.Split("("c)
    5. result.Add(part(0).Trim)
    6. Next
    7. Debug.Print(String.Join(Environment.NewLine, result.ToArray))
    Ich würde bei IndexOf noch ein Offset angeben (ich hoffe mal das geht unter .Net ^^).
    Sollte es folgende Situation geben:
    "blabla);is klar(ja ne);" dann kriegst du Probleme beim Entfernen.
    Also sowas wie:

    VB.NET-Quellcode

    1. Dim b1 As Integer = items(i).IndexOf("("C)
    2. 'Index der öffnenden Klammer
    3. Dim b2 As Integer = items(i).IndexOf(")"C, b1)
    4. 'Index der Schließenden Klammer
    5. 'Klammern mit Inhalt entfernen
    6. items(i) = items(i).Remove(b1, b2 - b1)

    Ausgehend jetzt von @Koopakiller:
    Am elegantesten ist es immer mit Regex, weil man da fast beliebig viele Kriterien reinbringen kann.

    VB.NET-Quellcode

    1. Dim text1 As String = "bombastisch;übermässig;üppig;gepfeffert (umgangssprachlich);horrend" & Environment.NewLine & "präoperativ (fachsprachlich);vor der Operation"
    2. text1 &= ";"
    3. Dim pat1 As String = "(?<word>\b[^;()\n]+\b).*?[;|\n]"
    4. For Each match1 As Match In Regex.Matches(text1, pat1)
    5. Debug.WriteLine(match1.Groups("word").Value)
    6. Next


    Edit:
    Ich bin davon ausgegangen, dass die Klammern immer hinter dem Begriff stehen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „markus.obi“ ()

    Wie schon erwähnt wurde: IndexOf bei so etwas simplem ist da leistungsschonend. Übrigends gehen alle davon aus, dass die Klammern richtig sind, was ist aber wenn nicht?
    So, und jetzt nochmal für alle Skeptiker. Regexy ist einfgach nur Langsam. Ich habe folgendes Programm geschrieben:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim sw As New Stopwatch()
    3. Dim s As String = "1234(A)" & vbCrLf & "12(B)34" & vbCrLf & "(c)1234"
    4. Dim a As String
    5. sw.Start()
    6. For i As Integer = 0 To 100000
    7. a = Regex.Replace(s, "\(\b+\)", "")
    8. Next
    9. sw.Stop()
    10. Console.WriteLine(sw.ElapsedTicks)
    11. sw.Reset()
    12. Dim b1 As Integer = 0
    13. Dim b2 As Integer = 0
    14. sw.Start()
    15. For i As Integer = 0 To 100000
    16. a = s
    17. While a.Contains("("c) 'Solange ausführen, wie Klammern enthalten sind
    18. b1 = a.IndexOf("("c)
    19. b2 = a.IndexOf(")"c, b1)
    20. a = a.Remove(b1, b2 - b1 + 1)
    21. End While
    22. Next
    23. sw.Stop()
    24. Console.WriteLine(sw.ElapsedTicks)
    25. sw.Reset()
    26. Console.ReadKey()
    27. End Sub


    Regex ist nach mehrmaligem testen im Relasemodus um die 3mal langsamer!

    @Mangafreak1995
    Wer hat in meinen Dateien herumgefuscht? Bei Dateien die ich erstelle, gehe ich auch davon aus das Sie richtig sind. Höchstens baue ich noch einen TryCatch block ein.

    @Mangafreak1995
    Stimmt, das Offset anzugeben ist natürlich besser.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Koopakiller“ ()

    @xtts02: Ich will nicht Anwender deiner Programme sein.
    @Koopakiller: Wenn er die Dateien selbst erstellen sollte kann er die Klammern gleich weglassen.
    @Mangafreak1995
    Es könnte aber auch sein, das die Klammern Zusatzinfos sind, die im jetzigen Fall einfach nicht benötigt werden. In einem anderen Fall aber schon. Vielleicht soll die zukünftige Programmversion auch einfach keine Zusatzinfos mehr unterstützen, weswegen diese jetzt entfernt werden müssen. Es gibt so viele Ideen/Lösungsmöglichkeiten. Letzten Enders muss der Fragesteller entscheiden.