Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 提取最后一次出现的输入字符的Haskell函数_String_List_Function_Haskell_Winghci - Fatal编程技术网

String 提取最后一次出现的输入字符的Haskell函数

String 提取最后一次出现的输入字符的Haskell函数,string,list,function,haskell,winghci,String,List,Function,Haskell,Winghci,我在编写这个函数时遇到了问题,它接受一个字符和一个字符列表,然后消除列表中最后出现的输入字符。我能够使用下面的函数取出第一次出现的输入字符: fun :: Char -> String -> String fun c (s:ss) | s == c = ss | otherwise = s : fun c ss fun _ [] = [] 我需要的帮助是如何修改此函数以去掉输入字符的最后一个匹配项,而不是第一个匹配项。结果应该是类似于fun'c'“abcdccytrc”返回

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

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

我需要的帮助是如何修改此函数以去掉输入字符的最后一个匹配项,而不是第一个匹配项。结果应该是类似于
fun'c'“abcdccytrc”
返回
“abcdccytr”

好的,下面是我的想法:

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
),请保留当前字符并将此函数应用于字符串的其余部分


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

正如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')

如何反转字符串,然后使用函数?这可能不是你想要的,但它会起作用。我在想这个问题,我试过了,我试着把它都放在一个函数中。是的,这就是为什么我试着用一个函数来回答。但正如威尔·内斯和齐对我的回答所评论的那样,有更好的解决方案。我希望您能将已接受的答案转换为@SimonShine的答案,但谢谢!将结果与原始字符串进行比较将使函数在二次时间内运行。但是你不需要比较来找出结果——首先是你建造的。你只需要向自己发出信号,不管角色是否被移除。您可以返回
(String,Bool)
,或者返回
字符串或字符串的值。这看起来效率很低。每次调用两次递归调用似乎都表明了指数级的复杂性。对递归调用进行因式分解应该使其成为二次函数,这仍然远远不是通过反转得到的线性复杂度。@chi是的,我知道这非常低效,但实际上我才刚刚开始学习Haskell:我想尝试返回一个布尔值来改进这一点,但我不知道如何在Haskell中实现这一点。这就是为什么我建议把绳子也倒过来。@Willenss。。。事实上,我认为OP应该接受Simon下面的答案,因为这些原因(效率低下和更好的编码)。