Haskell:如何替换给定索引处的字符串字符?

时间:2021-01-09 22:16:48

标签: haskell

我正在寻找一个函数来替换给定索引处的字符。

例如:

replace 4 '!' "Hello World!"
-- Output: "Hell! World!"

3 个答案:

答案 0 :(得分:2)

您可以使用replacement : strAfter稍微改进它,并使用安全尾函数防止索引大于字符串长度时出错:

safeTail :: [a] -> [a]
safeTail [] = []
safeTail (_:xs) = xs

replaceCharAtIndex :: Int -> Char -> String -> String
replaceCharAtIndex index replacement str = strHead ++ replacement : safeTail strAfter
    where (strHead, strAfter) = splitAt index str

但是应该小心:对于负索引,它将替换字符串的第一个字符。对于大于字符串长度的索引,它将追加到字符串。这两种情况本身都不是理想的行为。

我们可以通过检查负索引和空尾匹配来改变行为:

replaceCharAtIndex :: Int -> Char -> String -> String
replaceCharAtIndex index replacement str
    | index < 0 = … -- index located before the string
    | (_:xs) <- strAfter = strHead ++ replacement : xs
    | otherwise = …  -- index located after the string.
    where (strHead, strAfter) = splitAt index str

因此,这里我们有两个 来填充这些边缘情况的结果。

答案 1 :(得分:1)

如果有人正在寻找这样的功能或类似的功能,我想出了这个:

replaceCharAtIndex :: Int -> Char -> String -> String
replaceCharAtIndex index replacement str = strHead ++ [replacement] ++ drop 1 strAfter
  where (strHead, strAfter) = splitAt index str

用法:replaceCharAtIndex 4 '!' "Hello World!"

答案 2 :(得分:1)

有四种情况需要考虑:

  1. 列表为空或索引为负。
  2. 索引太大(大于或等于列表的长度)。
  3. 列表为非空,索引为 0。
  4. 列表非空且索引不为零。

在情况 1 中,我们返回输入不变:

replace k _ xs | null xs || k < 0 = xs

(这可以分为两个子案例

replace _ _ [] = []
replace k _ xs | k < 0 = xs

)

情况 2 通过递归隐式处理,直到我们到达情况 1。

情况 3 的处理方式是简单地返回添加到输入尾部的替换字符。

replace 0 c (x:xs) = c : xs

案例 4 是一个有趣的案例:替换列表的第 k 个元素与将列表的头部添加到替换尾部的第 k-1 个元素的结果相同。< /p>

replace k c (x:xs) = x : replace (k-1) c xs

k 太大时,我们最终会到达情况 1,因为 xs 会在 k 变为 0 之前变为空,从而绕过情况 3。