Page 1 of 2

Dobro_replace() question for Fred in last message

Posted: Fri May 15, 2009 1:57 pm
by dobro
:)

original text :
Text$= " coucou toto20 , coucou toto205"



*****************************************************
my procedure

Code: Select all

text2$=dobro_replace(Text$,  "toto20"   ,  "Leon"   ) 
result :
coucou Leon , coucou toto205
*****************************************************
Purebasic :

Code: Select all

text3$=ReplaceString(Text$,"toto20","Leon")
result :
coucou Leon , coucou Leon5

*****************************************************



my procedure :

[mode Recursif]




ProcedureDLL.s dobro_replace2(chaine$,chaine_cherche$,chaine_remplace$)
     ; by Dobro
    Static extrait1$,pos
     If pos= Len (chaine$)
        text2$=extrait1$
        pos=0 :extrait1$= ""
         ProcedureReturn text2$
     EndIf
    pos=pos+1
    extrait1$=extrait1$+ Mid (chaine$,pos,1)
    car_avant= Asc ( Mid (chaine$,pos-1,1)) ; le caractere avant
    car_apres= Asc ( Mid (chaine$,pos+ Len (chaine_cherche$),1)) ; ) ; le caractere apres
   extrait3$= Mid (chaine$,pos, Len (chaine_cherche$)) ; la chaine extraite
   
     If extrait3$=chaine_cherche$
         If (car_apres<48 Or (car_apres>57 And car_apres<65) Or (car_apres>90 And car_apres<97) Or car_apres>122 )
             If pos>1
                  If (car_avant<48 Or (car_avant>57 And car_avant<65) Or (car_avant>90 And car_avant<97) Or car_avant>122 )
                    extrait1$= Left (extrait1$, Len (extrait1$)-1)
                    extrait1$=extrait1$+chaine_remplace$
                    pos=pos+ Len (chaine_cherche$)-1
                 EndIf
             Else
                extrait1$= Left (extrait1$, Len (extrait1$)-1)
                extrait1$=extrait1$+chaine_remplace$
                pos=pos+ Len (chaine_cherche$)-1
             EndIf
         EndIf
     EndIf
    text2$=dobro_replace2(chaine$,chaine_cherche$,chaine_remplace$)
     ProcedureReturn text2$
EndProcedure


[mode iteratif]




ProcedureDLL.s dobro_replace2(chaine$,chaine_cherche$,chaine_remplace$)
     ; by Dobro
     For pos=1 To Len (chaine$)
        extrait1$=extrait1$+ Mid (chaine$,pos,1)
        car_avant= Asc ( Mid (chaine$,pos-1,1)) ; le caractere avant
        car_apres= Asc ( Mid (chaine$,pos+ Len (chaine_cherche$),1)) ; ) ; le caractere apres
        extrait3$= Mid (chaine$,pos, Len (chaine_cherche$)) ; la chaine extraite
        
         If extrait3$=chaine_cherche$
             If (car_apres<48 Or (car_apres>57 And car_apres<65) Or (car_apres>90 And car_apres<97) Or car_apres>122 )
                 If pos>1
                     If (car_avant<48 Or (car_avant>57 And car_avant<65) Or (car_avant>90 And car_avant<97) Or car_avant>122 )
                        extrait1$= Left (extrait1$, Len (extrait1$)-1)
                        extrait1$=extrait1$+chaine_remplace$
                        pos=pos+ Len (chaine_cherche$)-1
                     EndIf
                 Else
                    extrait1$= Left (extrait1$, Len (extrait1$)-1)
                    extrait1$=extrait1$+chaine_remplace$
                    pos=pos+ Len (chaine_cherche$)-1
                 EndIf
             EndIf
         EndIf
     Next pos
    
    text2$=extrait1$
    pos=0 :extrait1$= ""
     ProcedureReturn text2$
EndProcedure
[Version Library for tailbite]




Global text2$
ProcedureDLL.s dobro_replace(chaine$,chaine_cherche$,chaine_remplace$)
     ; by Dobro
     For pos=1 To Len (chaine$)
        extrait1$=extrait1$+ Mid (chaine$,pos,1)
        car_avant= Asc ( Mid (chaine$,pos-1,1)) ; le caractere avant
        car_apres= Asc ( Mid (chaine$,pos+ Len (chaine_cherche$),1)) ; ) ; le caractere apres
        extrait3$= Mid (chaine$,pos, Len (chaine_cherche$)) ; la chaine extraite
        
         If extrait3$=chaine_cherche$
             If (car_apres<48 Or (car_apres>57 And car_apres<65) Or (car_apres>90 And car_apres<97) Or car_apres>122 )
                 If pos>1
                     If (car_avant<48 Or (car_avant>57 And car_avant<65) Or (car_avant>90 And car_avant<97) Or car_avant>122 )
                        extrait1$= Left (extrait1$, Len (extrait1$)-1)
                        extrait1$=extrait1$+chaine_remplace$
                        pos=pos+ Len (chaine_cherche$)-1
                     EndIf
                 Else
                    extrait1$= Left (extrait1$, Len (extrait1$)-1)
                    extrait1$=extrait1$+chaine_remplace$
                    pos=pos+ Len (chaine_cherche$)-1
                 EndIf
             EndIf
         EndIf
     Next pos
    
    text2$=extrait1$
    pos=0 :extrait1$= ""
     ProcedureReturn text2$
EndProcedure




[call sample : for lib ]



Text$ = "aa Test_Procedure20(coucou) bb Test_Procedure205 (coucou) cc Test_Procedure20 (coucou) cc Test_Procedure20" + Chr (13)+ Chr (10)+ "(coucou)"

Debug dobro_replace(Text$, "Procedure20" , "xxx" )


Posted: Fri May 15, 2009 6:03 pm
by Trond
It can be done a bit simpler: :)

Code: Select all

Procedure.s trond_replace(Haystack.s, Needle.s, Seam.s)
  A.s = ReplaceString(" " + Haystack + " ", " " + Needle + " ", " " + Seam + " ")
  ProcedureReturn Right(Left(A, Len(a)-1), Len(a)-2)
EndProcedure
It's also about 15 times faster. 8)

But it doesn't take newlines into account.

Posted: Fri May 15, 2009 8:01 pm
by dobro
:?

your code :

Code: Select all

Haystack.s = "aa Test_Procedure20(coucou) bb Test_Procedure205 (coucou) cc Test_Procedure20 (coucou) cc Test_Procedure20" + Chr (13)+ Chr (10)+ "(coucou)"  
Needle.s="Procedure20"
Seam.s="toto"
CallDebugger
Procedure.s trond_replace(Haystack.s, Needle.s, Seam.s)
    A.s = ReplaceString(" " + Haystack + " ", " " + Needle + " ", " " + Seam + " ")
    ProcedureReturn Right(Left(A, Len(A)-1), Len(A)-2)
EndProcedure

Debug trond_replace(Haystack.s, Needle.s, Seam.s)

result :
aa Test_Procedure20(coucou) bb Test_Procedure205 (coucou) cc Test_Procedure20 (coucou) cc Test_Procedure20
(coucou)
?? no change !!!


my procedure


result :
aa Test_toto(coucou) bb Test_Procedure205 (coucou) cc Test_toto (coucou) cc Test_toto
(coucou)
you understand ?? :roll: :)

Posted: Fri May 15, 2009 8:31 pm
by dobro
another procedure :)
by Lionel_om (french forum)



Procedure.s SpecialReplaceString(Text$, FindMe$, ReplaceBy$)
    Protected index.l = 1, *char.c
    Protected lFindMe.l = Len (FindMe$), lReplBy.l = Len (ReplaceBy$)
    index = FindString (Text$, FindMe$, index)
     While index
        *char = PeekC (@Text$ + lFindMe + index - 1)
         If *char < '0' Or *char > '9'
            Text$ = Left (Text$,index-1) + ReplaceBy$ + Right (Text$, 1+ Len (Text$)-(index+lFindMe))
             ; Debug Text$
            index + lReplBy + 1
         Else
            index + lFindMe + 1
         EndIf
        index = FindString (Text$, FindMe$, index)
     Wend
     ProcedureReturn Text$
EndProcedure

Posted: Fri May 15, 2009 8:40 pm
by Deeem2031
Imho this should work too, but it doesn't :?

Code: Select all

Haystack.s = "aa Test_Procedure20(coucou) bb Test_Procedure205 (coucou) cc Test_Procedure20 (coucou) cc Test_Procedure20" + Chr (13)+ Chr (10)+ "(coucou)"  
Needle.s="Procedure20" 
Seam.s="toto"

Procedure.s Deeem2031_Replace(String.s, Find.s, Replace.s) 
  Protected regex, result.s
  regex = CreateRegularExpression(#PB_Any, "(?<![a-zA-Z0-9])"+Find+"(?![a-zA-Z0-9])")
  If regex
    result = ReplaceRegularExpression(regex, String, Replace)
    FreeRegularExpression(regex)
  EndIf
  ProcedureReturn result
EndProcedure

Debug Deeem2031_Replace(Haystack.s, Needle.s, Seam.s)

Posted: Fri May 15, 2009 8:45 pm
by dobro
:lol: :lol:


we have already tried the lib RegularExpression

and that is why "dobro_replace" is born :D

Posted: Fri May 15, 2009 8:49 pm
by Deeem2031
But it should work this way, this looks like a bug because all regex-tools i tried did it as expected (try for example: http://www.fileformat.info/tool/regex.htm). Only PB does not do it right.

Posted: Fri May 15, 2009 8:53 pm
by dobro
Fred can answer only :)

Re: Dobro_replace()

Posted: Fri May 15, 2009 9:13 pm
by AND51
dobro wrote:original text :
Text$= " coucou toto20 , coucou toto205"

...
result :
coucou Leon , coucou Leon5
Sorry, I don't understand the purpose. Should only the first match be replaced?

// edit:
Ah, I understand: you only want whole words to be replaced?

Re: Dobro_replace()

Posted: Fri May 15, 2009 9:36 pm
by Trond
AND51 wrote: // edit:
Ah, I understand: you only want whole words to be replaced?
Which is what I thought as well, but then it turns out my solution is incorrect because it only replaces whole words...

It would be a good idea to post an explanation of what the code actually does when you post a code.

Posted: Fri May 15, 2009 9:46 pm
by AND51

Code: Select all

Procedure.s replaceWholeWords(String.s, Find.s, Replace.s, caseInsensitive=0)
	String=" "+String+" "
	Find=" "+Find+" "
	Replace=" "+Replace+" "
	ReplaceString(String, Find, Replace, #PB_String_InPlace)
	ProcedureReturn Mid(String, 2, Len(String)-2)
EndProcedure

Procedure.s trond_replace(Haystack.s, Needle.s, Seam.s) 
  A.s = ReplaceString(" " + Haystack + " ", " " + Needle + " ", " " + Seam + " ") 
  ProcedureReturn Right(Left(A, Len(a)-1), Len(a)-2) 
EndProcedure

s.s="abc abc aBc aBC abc"
f.s="abc"
r.s="xXx"

a=ElapsedMilliseconds()
For n=1 To 1000000
	replaceWholeWords(s, f, r)
Next
a=ElapsedMilliseconds()-a

b=ElapsedMilliseconds()
For m=1 To 1000000
	trond_replace(s, f, r)
Next
b=ElapsedMilliseconds()-b

MessageRequester("AND51: "+Str(a), "Trond: "+Str(b))
Works like Trond's one, but is about 35% faster. :P


@ Trond:
Yeah, it would be much better, if there was an additional explanation of what the code does. I tried to understand the example, but first it looks like the first word should only be replaced.

Posted: Fri May 15, 2009 10:13 pm
by dobro
AND51 wrote:
@ Trond:
Yeah, it would be much better, if there was an additional explanation of what the code does. I tried to understand the example, but first it looks like the first word should only be replaced.
no ! i sorry , i dont speak englih !!

the procedure of purebasic for this exemple

Code: Select all

ReplaceString("Test_Procedure20(coucou) bb Test_Procedure205 (coucou) ","Procedure20","xxx")
for this string :
Test_Procedure20(coucou) bb Test_Procedure205 (coucou)

result : (no good !)
Test_xxx(coucou) bb Test_xxx5 (coucou)
no good because Test_Procedure205 is'nt Test_Procedure20 !!

my procedure replace juste Test_Procedure20
and not Test_Procedure205

for my procedure is différent ... you understand ??
*************************************************************

si un français passe par la

expliquez leur que ma procedure remplace de façon intelligente
elle ne confond pas


Test_Procedure20(coucou)
et
Test_Procedure205 (coucou)

et que si l'on veux remplacer juste 'Procedure20'
et bien seulement le premier cas sera remplacé
(Test_Procedure20(coucou))

parceque ma procedure reconnait "Procedure20"
et ne touchera pas a
"Test_Procedure205 (coucou)"
parceque 205 c'est pas 20 !! :)

Posted: Fri May 15, 2009 10:51 pm
by case
what dobro wan't to say is that his procedure only replace the EXACT MATCH , it not replace a part of a sentence if it match the search string...

for exemple you have "print printed printing print printed printing" as a string

with dobro's procedure if you replace 'print' by 'write'

you'll end up with "write printed printing write printed printing"

as you can see it replace only the exact match of the search string if the word is longer than the searched one it will not be replaced

the pb replacestring will leave you with

"write writeed writeing write writeed writeing"

hope it's clearer for you all as dobro seems to not be able to explain it right.

Posted: Fri May 15, 2009 11:05 pm
by AND51
Ah okay. So I did understand you correctly: you only replace entire words.
Then my procedure and Trond's procedure should work right.

Posted: Fri May 15, 2009 11:13 pm
by Demivec
AND51 wrote:Ah okay. So I did understand you correctly: you only replace entire words.
Then my procedure and Trond's procedure should work right.
Both of your code samples don't replace whole words that are followed by punctuation (i.e. one of ";.,(") or a carriage return. so they don't accomplish the same thing as dobro's.

Try your functions with this string:

Code: Select all

s.s = "abc abc aBc aBC abc" + Chr(13) + "abc() abc, abc; abc." ;source string
F.s = "abc" ;find string
r.s = "xXx" ;replace string
Your code and Trond's both produce:

Code: Select all

xXx abc aBc aBC abc
abc() abc, abc; abc.
dobro's code produces:

Code: Select all

xXx xXx aBc aBC xXx
xXx() xXx, xXx; xXx.
That means you may have trouble using either of your functions to replace strings in the text of a program's source code.