FindLastString() »»» Letztes Vorkommen von Strings ermitteln

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
al90
Beiträge: 1101
Registriert: 06.01.2005 23:15
Kontaktdaten:

Beitrag von al90 »

Ich hatte es mit einer Procedure und Memory-Befehlen versucht.
Weist schon, Peek + Poke und so. Brachte aber alles nix, hab den
Code auch nicht mehr.
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

AND51 hat geschrieben:Das ist doch im Prinzip, dasselbe was ich gepostet habe.
Aber bei dir hat man's nicht als Befehl/Procedure.
genau deshalb ist meins schneller <)
Und die optisch besseren Einrückungen fehlen. :|
Schönheit war nicht gefragt. Mein Code ist kürzer als Deiner :wink:

//Edit: Ach edel du hast ja auch was gepostet! hab ich nicht gesehen, als ich gepostet habe...
der von Edel geht nicht
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Benutzeravatar
nco2k
Beiträge: 892
Registriert: 08.09.2004 23:13

Beitrag von nco2k »

fast doppelt so schnell wie die version von AND51:

Code: Alles auswählen

Procedure FindLastString(String.s, StringToFind.s, CaseSensitive=1)
  
  If CaseSensitive = 0
    String = LCase(String)
    StringToFind = LCase(StringToFind)
  EndIf
  
  Protected StringLength = StringByteLength(String), StringToFindLength = StringByteLength(StringToFind), Offset = StringLength - StringToFindLength, CharacterLength = SizeOf(Character), Result
  
  While Offset > -1
    If CompareMemory(@String + Offset, @StringToFind, StringToFindLength)
      Result = Offset / CharacterLength + 1
      Break
    EndIf
    Offset - CharacterLength
  Wend
  
  ProcedureReturn Result
  
EndProcedure

Debug FindLastString("Diese Prozedur sucht von hinten. Deshalb sollte diese Prozedur performanter sein als die bisherigen Prozeduren.", "Prozedur")
ps: habs jetzt nicht gross getestet, wer fehler findet darf sie behalten. <)

c ya,
nco2k
~|__/
..o.o.. <--- This is Einkaufswagen. Copy Einkaufswagen into your signature to help him on his way to world domination.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Ach DAS meint ihr mit CompareMemory()... Ich gebe zu, das ist gut! Da hätte ich auch drauf kommen müssen...

Danke nco2k !!!! :allright:


> Und die optisch besseren Einrückungen fehlen.
>> Schönheit war nicht gefragt.
>>> -Größte Bequemlichkeit für den Benutzer
Ist es nicht Bequemlichkeit, dem Benutzer einen besseren Überblick über den Code zu bieten, damit dieser ihn besser ansehen/bearbeiten kann? Sonst muss er ja alles manuell einrücken... :wink:
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
ChristianK
Beiträge: 77
Registriert: 13.12.2004 14:55

Beitrag von ChristianK »

Edel hat geschrieben:

Code: Alles auswählen

Repeat
  lastpos = pos
  pos = FindString(haystack,needle,pos+1)
Until pos = 0 
bobobo hat geschrieben: der von Edel geht nicht
Natürlich geht der Code von Edel, und sogar bestens! Das Ergebnis steht korrekt in 'lastpos'. Einfach ud simpel. gefällt mir! Beste Programmierkunst!:allright:
AND51 hat geschrieben:

Code: Alles auswählen

Procedure.l FindLastString(String$, StringToFind$)
   Protected n, i, l=StringByteLength(String$)-SizeOf(Character), l2=StringByteLength(StringToFind$)-SizeOf(Character)
   Protected *String.Character, *StringToFind.Character
   For n=l To 0 Step -SizeOf(Character)
      *String=@String$+n
      *StringToFind=@StringToFind$
      If *String\c = *StringToFind\c
         For i=0 To l2 Step SizeOf(Character)
            *String=@String$+n+i
            *StringToFind=@StringToFind$+i
            If *String\c <> *StringToFind\c
               Break
            EndIf
         Next
         If i = l2+SizeOf(Character)
            Break
         EndIf
      EndIf
   Next
   ProcedureReturn (n+SizeOf(Character))/SizeOf(Character)
EndProcedure


Debug FindLastString("Ich liebe PureBasic! Du auch?", "Ich")
man kann alles bis zur unleserlichkeit (Geschwindigkeits-)optimieren. Aber bringts das? muss jede Zeile 5x lesen um den Sinn zu versthene. 21 Programmzeilen wo 4 genügen umd das Problem zu lösen? :?
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Hallo!

Ich habe mal CopyMemoryString() benutzt. Hat eine eingebaute Case(In)Sensitive-Funktion, die sich um alles kümmert.
Außerdem ist meine Prozedur kürzer und ein paar ms schneller als die von co2k:

Code: Alles auswählen

Procedure.l FindLastString(String$, StringToFind$, CaseInSensitive=0)
	Protected length=Len(StringToFind$), *position=@String$+(Len(String$)-length)*SizeOf(Character)
	While @String$ < *position
		If CompareMemoryString(*position, @StringToFind$, CaseInSensitive, length) = 0
			ProcedureReturn (*position-@String$)/SizeOf(Character)+1
		EndIf
		*position-SizeOf(Character)
	Wend
	ProcedureReturn 0
EndProcedure


Debug FindLastString("Am Anfang sollte der Suchstring sollte stehen, um die Prozedur zu fordern!", "anfang", 1)

> Aber bringts das? muss jede Zeile 5x lesen um den Sinn zu versthene.
Dazu kann man den Code ja kommentieren. Ich habs aber nicht gemacht, weil ich ja weiß, wie der Code arbeitet.

Der von dir zitierte Code ist aber schon wieder alt, hab hier einen neueren, wo man den SInn auch mit 1x Lesen erfassen kann :wink:
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

>> man kann alles bis zur unleserlichkeit (Geschwindigkeits-)optimieren. Aber bringts das?
Nur wenn Geschwindigkeit erforderlich ist. Dann kann man aber durch
verzicht auf z.B. Peek, Poke, FindString, StringField usw. eine Menge ein-
sparen. Wenn ich z.B. einen Parser schreibe, sind diese Optimierungen
unverzichtbar. Wenn ich sowas nicht so oft benötige, mit kurzen Texten,
dann kann man sich die Umstände natürlich sparen, weil das bringts dann
nicht :mrgreen:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

ChristianK hat geschrieben:
bobobo hat geschrieben: der von Edel geht nicht
Natürlich geht der Code von Edel, und sogar bestens! Das Ergebnis steht korrekt in 'lastpos'. Einfach ud simpel. gefällt mir! Beste Programmierkunst!:allright:
achso .. blind war


Das stand aber sehr nutzerunfreundlich nicht dabei. :D
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

Was haltet ihr von der Idee:

Den String umdrehen, den SuchString umdrehen.
Dann FindString()

Dann braucht man nur noch von der Gesamtlänge des Strings die ermittelte Position abziehen und weiß, wo das letzte Vorkommen ist.

Nun braucht man sich nur noch um die schnellste Methode zu kümmern, die den String umdreht.

Aber schneller als der von Edel wird es wohl auch nicht sein.
Naja, wenn vergleichen lange dauert und viele SuchStrings drin sind, dann ist meine Idee vielleicht einen Tick angesagter.

Zu Edel: Ich denke, genauso ist es gedacht gewesen, deshalb kann man die Position gleich angeben und muss nicht immer erst Stückeln und von den Stücken dann die Position finden.

Edel zeigt, was man alles schaffen kann, wenn man zwei Minuten mal die Augen auf macht und eine Vision hat :shock:

:freak:
Zuletzt geändert von Xaby am 24.04.2007 21:33, insgesamt 1-mal geändert.
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

Xaby hat geschrieben:Was haltet ihr von der Idee:

Den String umdrehen, den SuchString umdrehen.
Dann FindString()

Dann braucht man nur noch von der Gesamtlänge des Strings die ermittelte Position abziehen und weiß, wo das letzte Vorkommen ist.

Nun braucht man sich nur noch um die schnellste Methode zu kümmern, die den String umdreht.

:freak:
Man kann auch einfach von hinten suchen.
Das versuche ich gerade in inline-Assembler umzusetzen. Da ich da aber selber noch Anfänger bin, dauert das noch ein bissel. :D
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Antworten