2015-11-12 45 views
3
我无法写这个函数,它接受一个字符,字符列表

中最后一次出现,则消除了在列表中输入字符的最后一次出现。我能拿出输入字符中第一次出现低于我的功能:Haskell的函数,它接受了输入的字符

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

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

+5

如何反转字符串,然后使用函数?这可能不是你想要的,但它会起作用。 – Numeri

+0

我在想这件事,我确实尝试过,我试图把它全部保留在一个函数中。 –

+1

是的,这就是为什么我试图在一个函数中回答。但是,正如威尔尼斯和凯对我的回答评论的那样,有更好的解决方案。如果您将接受的答案转换为@SimonShine的答案,我更喜欢它,但谢谢! – Numeri

回答

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 

于是威尔内斯指出,返回其最后一次出现被删除的字符串,一布尔值来表示当前事件是否应该被删除,是另一种:

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

从这个

除此之外,我想扭转字符串,然后调用原始的功能,然后再倒车了,就像我在评论暗示,可能会更容易理解,但是这只是意见。

+2

将结果与原始字符串进行比较将使您的函数在二次时间内运行。但是你不需要进行比较就可以找出结果 - 这是你首先建立它的原因。你只需要向你自己发信号,无论角色是否被移除。您可以返回'(String,Bool)'或者'Either String String'值。 –

+3

它看起来效率很低。两次递归调用每次调用似乎都表明指数复杂性。对递归调用进行因式分解应该使其具有二次性,这与通过反转获得的线性复杂度相差甚远。 – chi

+0

@chi是的,我知道这是非常低效的,但其实我只是刚刚开始学习Haskell:我认为试图返回一个布尔值,以改善这一点,但我不知道怎么做,在Haskell。这就是为什么我建议倒转字符串的原因。 – Numeri