【问题标题】:Haskell replace multiple substrings with regex in a single passHaskell 一次性用正则表达式替换多个子字符串
【发布时间】:2019-08-23 00:34:20
【问题描述】:

假设我有一个字符串s 和一个字符串元组列表ts,其中元组中的第一个元素是s 的子字符串,我想用相应的第二个元素替换。就我而言,字符串s 将始终是一个以空格分隔的不同单词列表;此外,我希望将s 中的每个单词全部替换为ts 中的相应值(我希望我的意图在这里很清楚)。对此的第一次尝试可能是:

import qualified Text.Regex as R -- from regex-compat    

replaceAllIn :: String -> [(String, String)] -> String
replaceAllIn = foldl (\acc (k, v) -> R.subRegex (R.makeRegex k) acc v)

当然,当一个键是另一个键的子字符串时,这不起作用

λ> s = "blah blahblee"
λ> ts = [("blah", "asdf"), ("blahblee", ";lkj")]
λ> replaceAllIn s ts
"asdf asdfblee"

因为第一个键在第一次通过时替换了两次出现的“blah”,而在第二次通过时留下一个不再有任何匹配“blahblee”的字符串。

有没有办法通过字符串一次性实现我想要的?或者是否有一种内置方式(在某个库中)一次替换多个模式?

编辑:发布后我立即意识到我不知道为什么我在这里使用正则表达式。但是,如果我用 MissingH 的 Data.String.Utils 中的 replace 替换正则表达式替换,问题仍然有效。

【问题讨论】:

  • 当字符串包含"foobarbaz"时,如果你想用"marmoset"替换"foobar",用"barbaz"替换"elephant"会发生什么?
  • 你能不能先对ts进行排序以替换最长的字符串?
  • @Cirdec 我很抱歉。我的问题还不清楚。编辑以反映在我的情况下不会发生这种情况(元组列表中会有一个“foobarbaz”键)。
  • @jkeuhlen 那应该可以。感谢您的洞察力!
  • 错字:lambda 表达式的参数必须用空格而不是逗号分隔,请参阅\acc,。否则,很好的 Haskell 正则表达式代码。

标签: regex haskell


【解决方案1】:

扩展我之前的评论,您可以先处理要替换的最长字符串:

λ> s = "blah blahblee"
λ> ts = [("blah", "asdf"), ("blahblee", ";lkj")]
λ> import qualified Data.List as L
λ> replaceAllIn s (L.sortOn fst ts)
"asdf ;lkj"

【讨论】:

    【解决方案2】:

    在我的例子中,字符串s 将始终是以空格分隔的不同单词列表;此外,我希望将s中的每个单词全部替换

    我看到的第一步是用空格将字符串拆分(或分隔)成单词。

    接下来,按照@keuhlen 的建议,我将替换对从最长到最短进行排序。

    在那之后,问题应该很简单,并且子字符串搜索速度很快,因为它会按单词边界前进。

    (一个额外的优化可以是按长度对搜索模式进行分组,例如在树或数组中,这样对于较短的输入词,永远不会考虑较长的模式。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-11
      • 1970-01-01
      • 1970-01-01
      • 2019-04-17
      • 2012-07-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多