A REPLACE( ) function 
Author Message
 A REPLACE( ) function

Maybe this exists and I've missed it. (Which wouldn't be the first
time.)

More than once I have wished for a function that would find all
occurences of PATTERN in STRING and replace them with NEW.  Both PATTERN
and NEW are arbitary strings rather than single characters.

Something like this:
string='A silly example.'
pattern='l'
new='r2'
output=replace(pattern,string,new)

output would be set to 'A sir2r2y exampr2e.'

I find that I need such an operation often enough that a DLL function
would be very handy.  It is such a common operation I am intrigued that
I haven't found such a function.

Does one exist under OS/2?

Thank you.

Doug Rickman



Sun, 04 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function

Quote:

>Maybe this exists and I've missed it. (Which wouldn't be the first
>time.)

>More than once I have wished for a function that would find all
>occurences of PATTERN in STRING and replace them with NEW.  Both PATTERN
>and NEW are arbitary strings rather than single characters.

>Something like this:
>string='A silly example.'
>pattern='l'
>new='r2'
>output=replace(pattern,string,new)

>output would be set to 'A sir2r2y exampr2e.'

>I find that I need such an operation often enough that a DLL function
>would be very handy.  It is such a common operation I am intrigued that
>I haven't found such a function.

Just wrote this ... call to this is:

     New = replace(Old,Find,Replace)
         where - New = your new string with replaces in place
                 Old = the original string
                 Find = the pattern you want to find
                 Replace = the new string to change all "finds" to

To make it case-insensitive, change both "pos(F,B)" to
"pos(translate(F),translate(B))"

Replace: procedure
   parse arg B,F,R
   P = pos(F,B)
   do while P>0
      B = delstr(B,P,length(F))
      B = insert(R,B,P-1)
      P=pos(F,B)
   end
return B


____________  \_______________/ www.geocities.com/~cejb
\__________/      / /
     __\ \_______/ /__         "The heck with the Prime Directive,
     \_______________/(-        let's destroy something!"



Sun, 04 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function

Quote:
>Maybe this exists and I've missed it. (Which wouldn't be the first
>time.)

>More than once I have wished for a function that would find all
>occurences of PATTERN in STRING and replace them with NEW.  Both PATTERN
>and NEW are arbitary strings rather than single characters.
[snipped]

>Doug Rickman

I don't know about your installation, but I found the following in the
Regina REXX documentation, and I've verified that it works in Regina 0.08d
on Windows NT:

   CHANGESTR(needle, haystack, newneedle )

   This function was introduced with the REXX ANSI Standard.  Its purpose is
to
   replace all occurrences of needle in the string haystack with newneedle.
   The function returns the changed string.

   If haystack does not contain needle, then the original haystack is
returned.

   CHANGESTR(a,fred,c)                -> fred
   CHANGESTR(,,x)                     ->
   CHANGESTR(a,abcdef,x)              -> xbcdef
   CHANGESTR(0,0,1)                   -> 1
   CHANGESTR(a,def,xyz)               -> def

   CHANGESTR(a,,x)                    ->
   CHANGESTR(,def,xyz)                -> def
   CHANGESTR(abc,abcdef,xyz)          -> xyzdef
   CHANGESTR(abcdefg,abcdef,xyz)      -> abcdef
   CHANGESTR(abc,abcdefabccdabcd,z)   -> zdefzcdzd

--
Regards,
Vidar Tysse    -   aka  "vtsystem AT bgnett DOT no"



Sun, 04 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function

Quote:


> >Maybe this exists and I've missed it. (Which wouldn't be the first
> >time.)

> >More than once I have wished for a function that would find all
> >occurences of PATTERN in STRING and replace them with NEW.  Both PATTERN
> >and NEW are arbitary strings rather than single characters.

> >Something like this:
> >string='A silly example.'
> >pattern='l'
> >new='r2'
> >output=replace(pattern,string,new)

> >output would be set to 'A sir2r2y exampr2e.'

> >I find that I need such an operation often enough that a DLL function
> >would be very handy.  It is such a common operation I am intrigued that
> >I haven't found such a function.

> Just wrote this ... call to this is:

>      New = replace(Old,Find,Replace)
>          where - New = your new string with replaces in place
>                  Old = the original string
>                  Find = the pattern you want to find
>                  Replace = the new string to change all "finds" to

> To make it case-insensitive, change both "pos(F,B)" to
> "pos(translate(F),translate(B))"

> Replace: procedure
>    parse arg B,F,R
>    P = pos(F,B)
>    do while P>0
>       B = delstr(B,P,length(F))
>       B = insert(R,B,P-1)
>       P=pos(F,B)
>    end
> return B

Chris's exec is great but it doesn't deal with the situation where the
replace string contains the pattern being sought (this results in an
infinite loop). Also he inverted the pattern (F) and string (B)
fields. The code below copes with the infinite loop problem and it
also puts the arguments in the order requested:



prevent */
/* infinite loop when the find str is contained in the replace str */

   parse arg F,B,R
   P = pos(F,B)
   spos = 0
   do while P>0
      B = delstr(B,P,length(F))
      If Length(R) > 0 Then B = insert(R,B,P-1)
      spos = P + Length(R) - 1
      P=pos(F,B,spos)
   end
return B

Undoubtedly I've shot myself in the foot somewhere there and missed
something which someone is sure to catch.  ;-)

Quote:

> ____________  \_______________/ www.geocities.com/~cejb
> \__________/      / /
>      __\ \_______/ /__         "The heck with the Prime Directive,
>      \_______________/(-        let's destroy something!"

Michael Motek
Senior Programmer/Analyst
University of Victoria


Sun, 04 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function

Quote:

> Maybe this exists and I've missed it. (Which wouldn't be the first
> time.)

> More than once I have wished for a function that would find all
> occurences of PATTERN in STRING and replace them with NEW.  Both PATTERN
> and NEW are arbitary strings rather than single characters.

> Something like this:
> string='A silly example.'
> pattern='l'
> new='r2'
> output=replace(pattern,string,new)

> output would be set to 'A sir2r2y exampr2e.'

> I find that I need such an operation often enough that a DLL function
> would be very handy.  It is such a common operation I am intrigued that
> I haven't found such a function.

> Does one exist under OS/2?

> Thank you.

> Doug Rickman

When this question comes up, here's the answer that Mike Cowlishaw
posts.  I have this one hung on the wall next to my PC and on disk where
I re-use it all of the time for this kind of operation.  Mike's post:

**********
Here's my CHANGE.REX (circa 1982). It should be reasonably fast on most
platforms.

/*Internal function:  CHANGE(string,old,new)
(Like XEDIT "C/old/new/1 *")

Changes all occurrences of "old" in "string" to "new".
If "old"=='', then "new" is prefixed to "string".  MFC */

Change: procedure
  parse arg string, old, new
  if old='' then return new||string
  out=''
  do while pos(old,string)\=0
    parse var string prefix (old) string
    out=out||prefix||new
    end
  return out||string



Mon, 05 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function
Thank you all.  Hopefully the OS/2 version of REXX will get the ANSI
CHANGESTR() routine at some point.

Out of curiousity I did a quick little time test on the two routines
posted.  For a thousand iterations (units are seconds):

0.240000 - By Mike Cowlishaw
0.470000 - By Michael Motek & Chris Barnabo
0.430000 - By Michael Motek & Chris Barnabo without the internal 'If
Length(R) > 0 Then ... '

The strings used:

string='Mary had a little lamb, and the doctor fainted.'
old=' a'
new=' another'

Again, thank you all very much.

Doug Rickman

Quote:






Mon, 05 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function

Quote:

>Thank you all.  Hopefully the OS/2 version of REXX will get the ANSI
>CHANGESTR() routine at some point.

>Out of curiousity I did a quick little time test on the two routines
>posted.  For a thousand iterations (units are seconds):

>0.240000 - By Mike Cowlishaw
>0.470000 - By Michael Motek & Chris Barnabo
>0.430000 - By Michael Motek & Chris Barnabo without the internal 'If
>Length(R) > 0 Then ... '

Interesting!  Usually I've found parse to be slower than other functions
for breaking a string down, but I'll bet Mike C's use of concatenation is
faster than the insert() that Mike M. and I had in our function (Mike M, by
the way, good catch and improvement on my version!)


____________  \_______________/ www.geocities.com/~cejb
\__________/      / /
     __\ \_______/ /__         "The heck with the Prime Directive,
     \_______________/(-        let's destroy something!"



Mon, 05 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function

Quote:

>>Thank you all.  Hopefully the OS/2 version of REXX will get the ANSI
>>CHANGESTR() routine at some point.

>>Out of curiousity I did a quick little time test on the two routines
>>posted.  For a thousand iterations (units are seconds):

>>0.240000 - By Mike Cowlishaw
>>0.470000 - By Michael Motek & Chris Barnabo
>>0.430000 - By Michael Motek & Chris Barnabo without the internal 'If
>>Length(R) > 0 Then ... '

>Interesting!  Usually I've found parse to be slower than other functions
>for breaking a string down, but I'll bet Mike C's use of concatenation is
>faster than the insert() that Mike M. and I had in our function (Mike M, by
>the way, good catch and improvement on my version!)

I read a piece on recursion the other day, and I thought it might be applied
to this problem.  This is what I came up with, based on Mike Cowlishaw's
CHANGE routine:

/* Vidar Tysse's recursive VTCHANGE(haystack,needle,newneedle) */
vtChange: procedure
   parse arg string, old, new
   if old='' then return new||string
   parse var string prefix (old) string
   if string=='' then return prefix
return prefix||new||vtChange(string,old,new)

It's shorter than Chris/Mike M's REPLACE(), and it runs a little quicker,
according to tests that I have done with Regina REXX.  The only problem is
call stack overflow, I guess.
   The following is a typical output of a test program I wrote.  Let me know
if you want me to post the test REXX as well - it's a bit lengthy.
------------------
Changing " a" to " another" in "Mary had a little lamb, and the
doctor fainted." for 10000 iterations:
[..some output removed..]
...and here are the results of the WIN32 REXX-Regina_0_08d 4.75 26 Mar 1998
jury:
   ChangeStr()...:  0.00008910 sec/call, i.e. 1.00 times slower than the BIF
   Change()......:  0.00020730 sec/call, i.e. 2.33 times slower than the BIF
   Replace().....:  0.00032440 sec/call, i.e. 3.64 times slower than the BIF
   vtChange()....:  0.00027440 sec/call, i.e. 3.08 times slower than the BIF
------------------

Since the test above only changes 2 occurrences, I ran the following test,
which changes 89 occurrences, and thus is a better comparison of the
routines:
------------------
Changing "a" to "another" in "Mary had a little lamb, and the
doctor fainted. More aaaaaaaaaaaaaaaas added
aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/
aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa." for 10000 iterations:
[..some output removed..]
   ChangeStr()...:  0.00011820 sec/call, i.e. 1.00 times slower than the BIF
   Change()......:  0.00187370 sec/call, i.e. 15.85 times slower than the
BIF
   Replace().....:  0.01126920 sec/call, i.e. 95.34 times slower than the
BIF
   vtChange()....:  0.00783830 sec/call, i.e. 66.31 times slower than the
BIF
------------------

Mike Cowlishaw's CHANGE() is impressive - always a lot faster than the two
others, and only from 2 to 16 times slower than the CHANGESTR() BIF in most
cases.  An exception is the case where both old and new strings are 1
character in length (e.g. replace all 'a' with 'b'), where ChangeStr()
really flies.

--
Vidar Tysse    -   aka  "vtsystem AT bgnett DOT no"



Tue, 06 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function

on 19 Aug 98  10:06:32 about A REPLACE( ) function...

Quote:
> Maybe this exists and I've missed it. (Which wouldn't be the first
> time.)
> More than once I have wished for a function that would find all
> occurences of PATTERN in STRING and replace them with NEW.  Both
> PATTERN and NEW are arbitary strings rather than single characters.
> Something like this:
> string='A silly example.'
> pattern='l'
> new='r2'
> output=replace(pattern,string,new)
> output would be set to 'A sir2r2y exampr2e.'
> I find that I need such an operation often enough that a DLL function
> would be very handy.  It is such a common operation I am intrigued
> that I haven't found such a function.
> Does one exist under OS/2?

/* For SAA REXX */
replace: procedure
parse arg in,string,out

if pos(in,string)=0 then return string

rstring=''
do while pos(in,string)>0
    parse var string before (in) string
    rstring=rstring||before||out
end

return rstring
/* End procedure */

/* For Object REXX */
::routine replace
use arg in,string,out

if string~pos(in)=0 then return string

rstring=''
do while string~pos(in)>0
    parse var string before (in) string
    rstring=rstring||before||out
end

return rstring
/* End routine */

For SAA REXX, you can nix the procedure label, save it to replace.cmd, and
put it in your path.  If you use it a lot in a program, though, it's faster
to paste it right in at the end.

For Object REXX, you can save it as anything, and do a ::requires with any
program that needs it.

Or just use the built-in changestr() function or string method.

Mike Ruskai SA/AG #1106

... I don't care about apathy.



Tue, 06 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function

on 19 Aug 98  16:45:13 about Re: A REPLACE( ) function...

Quote:
> parse arg F,B,R
> P = pos(F,B)
> spos = 0
> do while P>0
> B = delstr(B,P,length(F))
> If Length(R) > 0 Then B = insert(R,B,P-1)
> spos = P + Length(R) - 1
> P=pos(F,B,spos)
> end
> return B
> Undoubtedly I've shot myself in the foot somewhere there and missed
> something which someone is sure to catch.  ;-)

Looks OK to me, but using parsing and concatenation instead of delstr() and
insert() is 15% faster.

And using the built-in changestr() function or string method is 99% faster
than both our methods :)

Mike Ruskai SA/AG #1106

... Bring out your dead. <KLANK>  Bring out your dead.



Tue, 06 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function

Quote:

>I read a piece on recursion the other day, and I thought it might be applied
>to this problem.

Recursion is often not the most efficient way to solve a problem, despite
what they might tell you in computer science classes. :-)  Of course, if
you are programming in Haskell or ML then recursion is nice and elegant.

Quote:
>/* Vidar Tysse's recursive VTCHANGE(haystack,needle,newneedle) */
>vtChange: procedure
>   parse arg string, old, new
>   if old='' then return new||string

This of course doesn't work if you want to change spaces to other characters:
you should use == instead of = (I notice the original version also had this
fault).

Quote:
>   parse var string prefix (old) string
>   if string=='' then return prefix
>return prefix||new||vtChange(string,old,new)

A more serious fault is that this will return an incorrect result if the
"haystack" ends with an instance of the "needle".

Quote:
>Mike Cowlishaw's CHANGE() is impressive - always a lot faster than the two
>others, and only from 2 to 16 times slower than the CHANGESTR() BIF in most
>cases.  An exception is the case where both old and new strings are 1
>character in length (e.g. replace all 'a' with 'b'), where ChangeStr()
>really flies.

Of course, it could also be done with translate() in that case. :-)

FWIW, here is my attempt...

/* Ian Collier's change procedure: ichange(haystack, needle, newneedle) */
ichange: procedure
parse arg string, old, new
if old=='' then return new||string
len=length(old)
out=''
do forever
   parse var string left (old) test +(len) string
   if test=='' then leave
   out=out||left||new
end
return out||left

Tests:

/* Simple replacement */
str.1="Mary had a little lamb, and the doctor fainted."
old.1=" a"
new.1=" another"
/* Short string with lots of occurrences */
str.2="Mary had a little lamb, and the doctor fainted. More",
      "aaaaaaaaaaaaaaaas added aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/aa/"
old.2="a"
new.2="another"
/* long string with no occurrences */
str.3=copies("hello ",50)
old.3="xyz"
new.3="abc"
/* long string with only one occurrence */
str.4=copies("hello ",25)"world" copies("hello ",25)
old.4="world"
new.4="hello"
/* a test that translate() could perform */
str.5=str.2
old.5="a"
new.5="b"

Results:

Test 1:                        Test 2:
ichange          0.00292       ichange          0.0237
change           0.00305       change           0.0377
vtchange         0.00377       vtchange         0.0650
replace          0.00498       replace          0.1039

Test 3:                        Test 4:
replace          0.00245       ichange          0.00361
vtchange         0.00246       change           0.00372
change           0.00267       vtchange         0.00375
ichange          0.00300       replace          0.00441

Test 5:
translate        0.000947
ichange          0.0246
change           0.0322
vtchange         0.0597
replace          0.0837
--

------ http://www.comlab.ox.ac.uk/oucl/users/ian.collier/imc.html

New to this group?  Answers to frequently-asked questions can be had from
http://rexx.hursley.ibm.com/rexx/ .



Tue, 06 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function
Vidar - I'm kinda came in on the middle of this and missed Mike C's original
routine, so don't know if yours inherited a problem or created it.  Try

vtchange(a,a,b) --> ""

I fixed this by adding another IF statement after the "if old=''....":

   if string = old then return new

- Peter Buck

--oops, here's another problem: vtchange(a,,b) -->AB.  I'll have to think
about that....

Quote:
> I read a piece on recursion the other day, and I thought it
> might be applied
> to this problem.  This is what I came up with, based on Mike
> Cowlishaw's
> CHANGE routine:

> /* Vidar Tysse's recursive VTCHANGE(haystack,needle,newneedle) */
> vtChange: procedure
>    parse arg string, old, new
>    if old='' then return new||string
>    parse var string prefix (old) string
>    if string=='' then return prefix
> return prefix||new||vtChange(string,old,new)



Tue, 06 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function

on 20 Aug 98  10:41:38 about Re: A REPLACE( ) function...

Quote:
> Thank you all.  Hopefully the OS/2 version of REXX will get the ANSI
> CHANGESTR() routine at some point.

It's been in there at least since the release of Warp 4, over two years
ago.

It's in all versions of Object REXX.

Mike Ruskai SA/AG #1106

... Life is like MS Windows... you never know what you're gonna get.



Wed, 07 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function

[snip]
Quote:
>A more serious fault is that this will return an incorrect result if the
>"haystack" ends with an instance of the "needle".

I should have known it couldn't be that simple.  It was just too elegant :-)

[snip]

Quote:

>FWIW, here is my attempt...

>/* Ian Collier's change procedure: ichange(haystack, needle, newneedle) */
>ichange: procedure
>parse arg string, old, new
>if old=='' then return new||string
>len=length(old)
>out=''
>do forever
>   parse var string left (old) test +(len) string
>   if test=='' then leave
>   out=out||left||new
>end
>return out||left

I hereby declare your routine the winner of this little speed contest.

--
Vidar Tysse    -   aka  "vtsystem AT bgnett DOT no"



Fri, 09 Feb 2001 03:00:00 GMT  
 A REPLACE( ) function
All hail Ian, the conquering hero!  May the newly crowned rest in peace
upon his throne.

(At least for now, as the crown never rests easy.)   :-)

Doug Rickman

Quote:

> >/* Ian Collier's change procedure: ichange(haystack, needle, newneedle) */
> >ichange: procedure
> >parse arg string, old, new
> >if old=='' then return new||string
> >len=length(old)
> >out=''
> >do forever
> >   parse var string left (old) test +(len) string
> >   if test=='' then leave
> >   out=out||left||new
> >end
> >return out||left

> I hereby declare your routine the winner of this little speed contest.

> --
> Vidar Tysse    -   aka  "vtsystem AT bgnett DOT no"



Sat, 10 Feb 2001 03:00:00 GMT  
 
 [ 18 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Replacing function/class definitions across modules

2. Replace standard MESSAGE function in C4 with own message function

3. Replace String (Function)

4. Replacing InString Function

5. Replacing library functions ?

6. Two more Clipper Tools Functions replace with pure Clipper

7. Replacing intrinsic functions?

8. What replaces statement functions in Fortran9X?

9. Function for replacing characters that can't be used in a filename

10. Python function to replace special characters in HTML?

11. Python function to replace special characters in HTML?

12. replacing logic function

 

 
Powered by phpBB® Forum Software