【问题标题】:How to replace more than one element at the same time in a String (Haskell)如何在字符串中同时替换多个元素(Haskell)
【发布时间】:2013-04-29 07:15:27
【问题描述】:

我想以这样的 2 个列表为例;

find=["Hou","House","Mouse"]
repl=["Mou","Bird","House"]

所以当我给出这样的文字时;

"The House with Mouse is big"

输出应该是这样的;

"The Mouse with House is big"

所以我写了这个;

replace :: String->String->String->String
replace _ _ []=[]

replace find repl text
  = if take(length find) text == find
      then repl ++ replace find repl (drop (length find) text)
      else [head text] ++ (replace find repl (tail text))

replaceMore ::[String]->[String]->String->String
replaceMore _ _ []=[]
replaceMore _ [] _ =[]
replaceMore [] _ _ =[]
replaceMore find repl text
  = if (tail find) == [] || (tail repl)==[]
      then text
      else replaceMore (tail find)
                       (tail repl)
                       (replace (head find) (head repl) text)

返回

"The Mouse with Mouse is big"

所以它不像我想要的那样工作,我认为问题就在这里;

replaceMore _ _ []=[]
replaceMore _ [] _ =[]
replaceMore [] _ _ =[]

但我仍然不知道如何解决这个问题。所以有什么想法吗?

【问题讨论】:

  • 让人们轻松地帮助你。不要只说“它不起作用”:说如何它不起作用工作。 如果有错误消息, 将它们复制并粘贴到您的问题中。 如果代码运行但给出了错误的答案,然后给出以下示例:输入您的代码,错误的输出您的代码返回,正确的输出您希望您的代码返回。
  • 不,您的问题不在您认为的位置。整个想法是错误的。你不能用replace 构建replaceMore。您需要并行搜索所有模式,并替换找到的第一个。

标签: string list haskell replace


【解决方案1】:

我可能会给你一些关于工作算法的想法。

首先,您需要根据您的find 字符串将您的输入String 分成多个部分([String])。所以这个函数是

divideIntoParts :: [String] -> String -> [String]

类似于

divideIntoParts find "The House with Mouse is big"

给了

["The ", "Hou", "se with ", "Mouse", " is big"]

因此它从字符串中提取要替换的部分,但通过将其他部分保留在同一列表中来保留字母顺序。天真的实现可能看起来像这样

https://gist.github.com/Shekeen/5523749

接下来,您需要一个函数来扫描此列表并更换需要更换的部件。签名将是

replaceParts :: [String] -> [String] -> [String] -> String

类似

replaceParts find repl $ divideIntoParts find "The House with Mouse is big"

将会

"The Mouse with House is big"

所以你的完整 replace 函数看起来像

replacePatterns :: [String] -> [String] -> String -> String
replacePatterns find repl = (replaceParts find repl) . (divideIntoParts find)

此外,您确实需要实现更快的子字符串搜索算法并考虑将findrepl 替换为Data.Map

【讨论】:

  • 如何在没有 Data.List.Split 帮助的情况下编写 divideIntoParts 函数。我是新手,所以我无法克服“返回值”问题。我的意思是函数返回 [String] 所以我做不到类似-> else [[head text] ++ divideIntoParts find (tail text)]
  • 主要思想是在输入字符串中找到最左边的子字符串,它与来自find的字符串匹配。然后你会把你的字符串分成三部分:匹配子串之前,匹配子串,匹配子串之后。然后您递归地执行相同的操作,但将其应用于匹配子字符串之后的部分。稍后我会用实际代码更新我的答案,但我想你会明白的。
  • 是的,我也理解了我考虑过的算法,但由于“类型匹配错误”,我无法编写函数。函数返回 [String] 我必须将不匹配的部分绑定在一起并且它的 String.I 必须做 String ++ String 那么我将如何递归地做呢?如果你更新你的代码,我会很高兴,因为我不知道如何编写这个算法
  • 我已经实现了 divideIntoParts 函数的幼稚版本。你可以在这里看到它gist.github.com/Shekeen/5523749
【解决方案2】:

我可以看到两个错误:

  1. findrepl 的最后一个元素总是被忽略。当tail find == []tail repl == []replaceMore 回馈text;那应该是find == []repl == []的时候。

    但它们应该被早期的方程式捕捉到

    replaceMore _ [] _ =[]
    replaceMore [] _ _ =[]
    

    哪个,你现在应该可以看到,错了,应该是

    replaceMore _ [] text = text
    replaceMore [] _ text = text
    
  2. 但是输出会是

    "The House with House is big"
    

    还是错了。这是因为您正在构建replaceMorereplace。对于每个搜索词,您搜索文本,找到时替换它。所以你用"Mou"替换"Hou"(所以"House""Mouse"替换);然后你用"House"替换"Mouse"(意味着原来的"House"最终又变成了"House")。

    相反,您应该在文本中搜索一次,在搜索文本之前查找某个位置的每个搜索词。

【讨论】:

    猜你喜欢
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 2015-12-30
    • 2021-11-25
    • 1970-01-01
    相关资源
    最近更新 更多