如何在Haskell中使用列表理解和递归检测两个相邻的相同字符?



我试图写一个函数detadj :: String -> Bool,它需要一个字符串并返回true if字符串包含两个相邻的相同字符。例如:

detadj "" == False
detadj "s" == False
detadj "ss" == True
detadj "Misisipi" == False
detadj "Mississippi" == True
detadj "single-dash" == False
detadj "double--dash" == True

我有两个版本的函数,一个在列表推导中,在许多情况下是错误的,但最常见的是当detadjlc ["ss"]由于使用(x:y:xs)位而输出空列表时:

detadjlc :: String -> Bool
detadjlc [] = False
detadjlc [x] = False
detadjlc (x:y:xs) = head[ x == y && isAlpha x == isAlpha y | (x,y) <- zip (x:y:xs) xs ]

和递归(这在输入是detadjr [" ee"]时不起作用,它产生False而不是True):

detadjr :: String -> Bool
detadjr [] = False
detadjr [x] = False
detadjr (x:y:xs) | x == y = True
| otherwise = d xs

有哪些方法可以解决这些问题?

下面是一个使用列表推导式的迭代解。我们创建一个包含输入列表相邻元素的元组列表。然后比较元组中的元素。

detadjlc :: String -> Bool
detadjlc xs = or [x == y | (x, y) <- zip xs (tail xs)]

递归解决方案最好按照@chepner已经发布的方法完成。

您的递归函数很好,除了一个小细节:您忘记将y放回递归调用的列表中。(我认为ddetadjr的错别字。)仅仅因为xy不同,并不意味着yxs的第一个字符可能不相同。

detadjr :: String -> Bool
detadjr (x:y:xs) = (x == y) || detadjr (y:xs)
detadjr _ = False

(如果您先检查两个或两个以上字符的字符串,那么单例列表和空列表可以折叠成一个基本情况。)

相关内容

  • 没有找到相关文章

最新更新