Лучший способ заменить подстроку в haskell - PullRequest
6 голосов
/ 08 марта 2011

Проблема довольно проста: я должен заменить все вхождения "fooo" и всех его подстрок на "xyz".В 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 слова в настоящем приложении, и это странно).

Я буду рад, если кто-нибудь поможет мне с решением fast .


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).Более того, он может иметь неожиданный результат замены подстроки результата предыдущей замены.

Ответы [ 2 ]

7 голосов
/ 08 марта 2011

В пакете MissingH Data.String.Utils.replace .Если вам нужна только замена простой подстроки (а не регулярные выражения), это может быть то, что вам нужно.

4 голосов
/ 08 марта 2011

Пакет 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

...