3

我在编写这个函数时遇到了麻烦,该函数接受一个字符和一个字符列表,然后消除该输入字符在列表中的最后一次出现。我能够使用下面的函数取出第一次出现的输入字符:

fun :: Char -> String -> String
fun c (s:ss)
 | s == c   = ss
 | otherwise = s : fun c ss
fun _ [] = []

我需要帮助的是我应该如何修改此函数以取出输入字符的最后一次出现,而不是第一次出现。结果应该类似于fun 'c' "abcdccytrc"返回"abcdccytr"

4

2 回答 2

2

好的,这就是我想出的:

fun :: Char -> String -> String
fun c (s:ss)
 | ((fun c ss) == ss) && (s == c) = ss
 | otherwise                      = s : fun c ss
fun _ [] = []

本质上,如果s == c和字符串 ( ) 的其余部分ss通过在其上运行此函数而未更改(即,它不包含字符c),则返回剩余的字符。

如果不满足此要求(即字符串的其余部分c至少有一次该字符),则保留当前字符并将该函数应用于字符串的其余部分。

除此之外,我认为反转字符串然后调用您的原始函数,然后再次反转它,就像我在评论中建议的那样,可能更容易理解,但这只是意见。

于 2015-11-12T23:24:27.310 回答
2

正如 Numeri 所建议的,通过删除反向列表中的第一个匹配项来删除最后一个匹配项是一种方法:

removeFirst :: Char -> String -> String
removeFirst _ [] = []
removeFirst c1 (c2:cs) = if c1 == c2 then cs else c2:removeFirst c1 cs

removeLast :: Char -> String -> String
removeLast c1 = reverse . removeFirst c1 . reverse

正如 Will Ness 建议的那样,返回删除最后一次出现的字符串,以及指示是否应该删除当前出现的布尔值是另一种情况:

removeLast :: Char -> String -> String
removeLast c1 = snd . remLast
  where
    remLast :: String -> (Bool, String)
    remLast [] = (False, [])
    remLast (c2:cs) =
      case remLast cs of
        (True, cs') -> (True, c2:cs')
        (False, cs') -> if c1 == c2 then (True, cs') else (False, c2:cs')
于 2015-11-13T00:07:27.777 回答