haskell中子串替换的最佳方法

时间:2011-03-08 09:38:55

标签: haskell substring replace

问题很简单:我必须用“xyz”替换所有出现的“fooo”及其所有子串。例如,在Java中,我将这样做:

someString.replaceAll( "fooo|foo|fo", "xyz" )

它会做的伎俩。但在Haskell中,我发现没有有效的方法来使用正则表达式。首先,我读过这个:http://www.haskell.org/haskellwiki/Regular_expressions

实际上具有replace功能的唯一库是regex-posix,但它在性能上被认为“非常慢”。这个事实是不可接受的。另外我发现这个replace函数由于任何原因不符合给定模式的顺序,所以我得到这样的输出:

>replace "boo fooo boo" "xyz"
"boo xyzoo boo"

其他后端并不意味着这样的功能。

所以我决定编写简单的解决方法:

replaceFoo input =
    helper input []
    where
        helper ('f':'o':'o':'o':xs) ys = helper xs ("zyx" ++ ys)
        helper ('f':'o':'o':xs) ys = helper xs ("zyx" ++ ys)
        helper ('f':'o':xs) ys = helper xs ("zyx" ++ ys)
        helper (x:xs) ys = helper xs (x:ys)
        helper [] ys = reverse ys

虽然我发现这个功能不太好,但效果很好而且速度很快。但是现在我遇到了在这个替换中添加更多单词的必要性,我不喜欢再扩展helper模式的想法(我需要说实际应用中我实际上有4个单词)单数)。

如果有人帮助我使用快速解决方案,我会很高兴。


cebewee,感谢Data.String.Utils。但我担心如果要替换很多单词(“fooo”到“xyz”,“foo”到“xyz”,“fo”到“xyz”,“bar”到“quux”等等,这种方法很慢),因为为了让它工作,我将需要foldr (\str (from,to) -> replace from to str) input pairs或类似的东西,它将需要O(n * n)。更重要的是,它可能会取代先前替换结果的子串的意外结果。

3 个答案:

答案 0 :(得分:7)

MissingH包中有Data.String.Utils.replace。如果您只需要普通子串替换(而不是正则表达式),那么这可能就是您所需要的。

答案 1 :(得分:4)

regex-xmlschema软件包有一个 sed 函数,可能就是你要找的东西:

http://hackage.haskell.org/package/regex-xmlschema-0.1.3

特别参见:

http://hackage.haskell.org/packages/archive/regex-xmlschema/0.1.3/doc/html/Text-Regex-XMLSchema-String.html#v:sed

去年在Haskell-Cafe上讨论了字符串重写的选项:

http://www.haskell.org/pipermail/haskell-cafe/2010-May/077943.html

答案 2 :(得分:0)

通过replace-megaparsec软件包,您可以 搜索模式匹配项,然后编辑找到的匹配项。这是使用的解决方案 Replace.Megaparsec.streamEdit

>>> import Replace.Megaparsec
>>> import Text.Megaparsec.Char
>>> streamEdit (chunk "fooo" <|> chunk "foo" <|> chunk "fo") (const "xyz") "boo fooo boo"
"boo xyz boo"