<div dir="ltr">Roberto thanks!<br>Shame on me, to post code without enough testing :(<br>Yet, thanks to your comments *I think* I have found the bugs you wrote about and now my code works, please see corrected version below. <br>
Extra substring at the end was a result of using foldr with initial element of []. I fixed this with foldl and first chunk as its initial element.<br>Incomplete substitution in case of duplicate elements in the pattern was a bug in my 'takeOut' function that I have also fixed.<br>
Stiil the problem that I have not yet designed solution for is when a substring to replace extends from the end of a string to the next string. In other words - first part of substring ends the first string and second part of substring starts the second string. My algorithm currently does not account for such a case.<br>
<br>On the side: The more I use Haskell - the more I like it ! It helps me think about the problem I solve much more clearly then when I use imperative language.<br><br>Corrected code:<br><br>-- replace all occurances of "123" with "58" in a string:<br>
test = replStr "abc123def123gh123ikl" "123" "58"<br><br>{--<br>In a string replace all occurances of an 'old' substring with a 'new' substring<br>--}<br>replStr str old new = foldl ((\newSub before after -> before ++ newSub ++ after) new) firstChunk otherChunks<br>
where chunks = splitStr str old<br> firstChunk = head chunks<br> otherChunks = tail chunks<br>{--<br>Split string into a list of chunks. <br>Chunks are substrings located in a string between 'sub' substrings <br>
--}<br>splitStr str sub = mkChunkLst str sub []<br> where<br> -- mkChunkLst 'src string' 'substr-to-extract' 'list of chunks'<br> -- makes list of chunks located between 'substr-to-extract' pieces in src string <br>
mkChunkLst [] _ chunkLst = chunkLst<br> mkChunkLst str sub chunkLst = mkChunkLst after sub (chunkLst ++ [chunk])<br> where <br> (chunk, _, after) = takeOut str sub [] []<br><br>{--<br>Take out substring from a string.<br>
String is divided into:<br>"before substr" ++ "match" ++ "after substr"<br>where 'match' is substring to split out <br>--}<br><br>takeOut after [] before match = (before, match, after)<br>
takeOut [] _ before match = (before, match, [])<br>takeOut (x:xs) (y:ys) before match<br> | x == y = takeOut xs ys before (match ++ [x])<br> | otherwise = takeOut xs (y:ys) (before ++ [x]) []<br><br><br><br><div class="gmail_quote">
On Tue, Jul 22, 2008 at 7:39 PM, Roberto Zunino <<a href="mailto:zunino@di.unipi.it">zunino@di.unipi.it</a>> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d">Dmitri O.Kondratiev wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I wrote my own version, please criticize:<br>
<br>
-- replace all occurances of "123" with "58" in a string:<br>
test = replStr "abc123def123gh123ikl" "123" "58"<br>
</blockquote>
<br></div>
This is a tricky problem: first of all, you fail your own test! ;-)<br>
<br>
*Main> test<br>
"abc58def58gh58ikl58"<br>
<br>
(Note the extra 58 at the end.)<br>
<br>
Other common pitfalls:<br>
<br>
*Main> replStr "abc1123def" "123" "58"<br>
"abc1158def58"<br>
<br>
(extra 1 ?)<br>
<br>
*Main> replStr "abc12123def" "123" "58"<br>
"abc121258def58"<br>
<br>
(extra 12 ?)<br>
<br>
A useful function from Data.List: stripPrefix<br>
<br>
(Of course, there are more efficient string match algorithms)<br>
<br>
Regards,<br>
Zun.<br>
</blockquote></div><br><br clear="all"><br>-- <br>Dmitri O. Kondratiev<br><a href="mailto:dokondr@gmail.com">dokondr@gmail.com</a><br><a href="http://www.geocities.com/dkondr">http://www.geocities.com/dkondr</a>
</div>