Seite 1 von 1
Explode()
Verfasst: 22.12.2015 15:32
von Domino
So, um nicht nur zu nehmen, sondern auch einmal etwas ans Forum zurückzugeben, fange ich mit ein paar kleinen Hilfsroutinen an - hier: Explode(). Bedarf hatte schon TomS im Beitrag
http://www.purebasic.fr/german/viewtopi ... it=explode und mk-soft hat eine sicherlich effiziente, aber für Anfänger nicht so gut nachvollziehbare Lösung geschrieben.
Code: Alles auswählen
EnableExplicit
Dim Zeile.s(30)
Declare.l Explode(Trenner.s, String.s, Array Arr.s(1))
Explode(":", "23:59:42.32", Zeile())
;{ Explode()
; Explode() zerlegt eine Zeichenkette in ihre Bestandteil und das Trennzeichen kann auch eine kpl.
; Zeichenkette sein. Da man in Purebasic keine Felder aus Prozeduren zurückgeben kann, wird das Feld
; einfach als Parameter übergeben und die Ergebnisse dort eingetragen. Die Anzahl der belegten Fel-
; der wird als Integer zurückgegeben. Sollte das Feld nicht genügend Einträge haben, wird -1 zurück-
; gegeben.
Procedure.l Explode(Trenner.s, String.s, Array Arr.s(1))
Define i.l, Pos.l
i = 0 ;So sähe der Teil bis Until 0 in PHP aus:
Repeat ;$VolProf = explode(", ", $VolProfStr);
Pos = FindString(String, Trenner)
If Pos = 0
If Len(String) > 0 : Arr(i) = String : String = "" : EndIf
Break
EndIf
Arr(i) = Left(String, Pos-1)
String = Mid(String, Pos + Len(Trenner))
i + 1
If i > ArraySize(Arr()) : ProcedureReturn -1 : EndIf
Until 0
ProcedureReturn i
EndProcedure
;}
Re: Explode()
Verfasst: 22.12.2015 15:52
von Domino
Danke sehr!
Re: Explode()
Verfasst: 22.12.2015 15:56
von Kurzer
Also das Auftrennen geht auch einfacher - ohne FindString(), Mid() usw.:
Code: Alles auswählen
EnableExplicit
Define i
For i = 1 To 10
Debug StringField("23:59:42.32", i, ":")
Next i
Re: Explode()
Verfasst: 22.12.2015 15:58
von mhs
Kleiner Tipp: Verwende generell Integer .i statt Long .l, dann hast du bei x86/x64 Umstellung weniger Probleme.
Ich hab deinen Code mal auf eine LinkedList umgebaut, die verwende ich an der Stelle immer gerne:
Code: Alles auswählen
EnableExplicit
Declare.i Explode(Trenner.s, String.s, List Results.s())
NewList Zeile.s()
Explode(":", "23:59:42.32", Zeile())
ForEach Zeile()
Debug Zeile()
Next
;{ Explode()
; Explode() zerlegt eine Zeichenkette in ihre Bestandteil und das Trennzeichen kann auch eine kpl.
; Zeichenkette sein. Da man in Purebasic keine Felder aus Prozeduren zurückgeben kann, wird das Feld
; einfach als Parameter übergeben und die Ergebnisse dort eingetragen. Die Anzahl der belegten Fel-
; der wird als Integer zurückgegeben. Sollte das Feld nicht genügend Einträge haben, wird -1 zurück-
; gegeben.
Procedure.i Explode(Trenner.s, String.s, List Results.s())
Define.i i, Pos
ClearList(Results())
If Not Len(String) : ProcedureReturn 0 : EndIf
Repeat ;$VolProf = explode(", ", $VolProfStr);
Pos = FindString(String, Trenner)
If Pos = 0
AddElement(Results())
Results() = String
Break
EndIf
AddElement(Results())
Results() = Left(String, Pos-1)
String = Mid(String, Pos + Len(Trenner))
i + 1
ForEver
ProcedureReturn i
EndProcedure
;}
Hier die gleiche Variante mit StringField: (einfacher und kürzer, dafür nicht die schnellste)
Code: Alles auswählen
EnableExplicit
Declare.i Explode(Trenner.s, String.s, List Results.s())
NewList Zeile.s()
Explode(":", "23:59:42.32", Zeile())
ForEach Zeile()
Debug Zeile()
Next
;{ Explode()
; Explode() zerlegt eine Zeichenkette in ihre Bestandteil und das Trennzeichen kann auch eine kpl.
; Zeichenkette sein. Da man in Purebasic keine Felder aus Prozeduren zurückgeben kann, wird das Feld
; einfach als Parameter übergeben und die Ergebnisse dort eingetragen. Die Anzahl der belegten Fel-
; der wird als Integer zurückgegeben. Sollte das Feld nicht genügend Einträge haben, wird -1 zurück-
; gegeben.
Procedure.i Explode(Trenner.s, String.s, List Results.s())
Define.i i, Count
ClearList(Results())
Count = CountString(String, Trenner)
For i = 1 To Count + 1
AddElement(Results())
Results() = StringField(String, i, Trenner)
Next i
ProcedureReturn ListSize(Results())
EndProcedure
;}
Re: Explode()
Verfasst: 19.04.2016 18:17
von Sicro
Das ist ein unnötiger Zeitfresser.
Ich habe den Code mit ein paar Verbesserungen neu erstellt:
- String wird gelassen, wie er ist
- Array wird in der Größe automatisch angepasst
- Array wird in großen Schritten vergrößert, damit das Array nicht zu oft angepasst werden muss
Code: Alles auswählen
EnableExplicit
Procedure Explode(Separator$, String$, Array Output$(1))
Protected ArrayIndex, StartPos, SeparatorPos
ArrayIndex = -1
StartPos = 1
Repeat
ArrayIndex + 1
If ArraySize(Output$()) < ArrayIndex
ReDim Output$(ArrayIndex + 99) ; Wenn Output-Array zu klein ist, es um 100 Elemente vergrößern
EndIf
SeparatorPos = FindString(String$, Separator$, StartPos)
If SeparatorPos = 0
Output$(ArrayIndex) = Mid(String$, StartPos)
Break
EndIf
Output$(ArrayIndex) = Mid(String$, StartPos, SeparatorPos - StartPos)
StartPos = SeparatorPos + 1
ForEver
ReDim Output$(ArrayIndex) ; Array auf die wirklich notwendige Größe setzen
ProcedureReturn ArrayIndex
EndProcedure
Define CountOfItems, i
Dim Items$(0) ; Hier kann die Größe auch im Voraus vergrößert werden, z. B.: Dim Items$(100)
CountOfItems = Explode(":", "String1:String2:String3", Items$())
For i = 0 To CountOfItems
Debug Items$(i)
Next
Debug ArraySize(Items$())
Die Verwendung eines Arrays finde ich hier besser, weil man später sehr schnell auf die einzelnen Einträge zugreifen kann, was mit Linked Lists nicht gegeben ist:
PB-Hilfe: SelectElement() hat geschrieben:Anmerkungen
Da verknüpfte Listen intern keinen Index verwenden, springt diese Funktion zwangsläufig zu jedem Element in der Liste, bis die Zielposition erreicht ist, was bei einer großen Liste Zeit benötigt.
Re: Explode()
Verfasst: 22.04.2016 16:02
von Sicro
Wird in
CodeArchiv unter Strings/ExplodeStringIntoArray.pbi aufgenommen.
Code-Autor: Domino (Code verbessert durch Sicro)