我需要检查列表的最后一个元素是否为大写
例如"abc"
- False
,"abC"
- True
这就是我的尝试
checkLast :: [a] -> Bool
checkLast [] = False
checkLast [x] = if isUpper x then True else False
checkLast (x:xs) = if isUpper last then True else False
答案 0 :(得分:4)
递归思考。 checkLast (x:xs)
只是检查checkLast xs
:
checkLast :: [Char] -> Bool
checkLast [] = False
checkLast [x] = isUpper x
checkLast (x:xs) = checkLast xs
请注意,由于您使用isUpper
来检查字符串,因此更有意义的是类型应为[Char]
,而不是[a]
。
答案 1 :(得分:2)
您可以像其他答案演示一样使用递归。但是你也可以使用内置函数来构造这样的函数。
这里的两个相关函数是null :: [a] -> Bool
,它检查列表是否为空,以及last :: [a] -> a
获取最后一个元素。
现在我们可以构建一个函数:
import Data.Char(isUpper)
checkLast :: [Char] -> Bool
checkLast l = not (null l) && isUpper (last l)
因此,如果列表checkLast
不为空(True
),我们在此声明l
为not (null l)
;最后一个元素是大写字符isUpper (last l)
。
这可能比递归函数快一点,因为我们只测试[]
一次(在null
中)。 last
仅检查两种情况:[x]
和(x:xs)
,因此我们会保存[]
次检查。
当然这些函数与递归一起工作,但有时候查找辅助函数很有用,这样函数几乎可以自我解释:这里的函数说:“列表l
是{{1如果它不为空,则最后一个元素是大写“。
答案 2 :(得分:1)
带注释的固定版本:
import Data.Char (isUpper)
checkLast :: [Char] -> Bool -- it cannot be [a]: use of isUpper already limits possible type to [Char]
checkLast [] = False
checkLast [x] = isUpper x -- the if .. can be shorter
checkLast (x:xs) = checkLast xs -- drop first char and look at rest of string
答案 3 :(得分:1)
如果您希望这样做,避免显式递归的最简单方法可能是使用折叠:
lastMay :: [a] -> Maybe a
lastMay = foldl' (\_ x -> Just x) Nothing
checkLast = maybe True isUpper . lastMay
答案 4 :(得分:-2)
您也可以在没有任何递归的情况下执行以下操作
import Data.Char
checkLast :: String -> Bool
checkLast = (&&) <$> not . null <*> isUpper . head . reverse
应用运算符<*>
是一个理想的工具,可以将公共参数(此处为输入字符串)提供给两个不同的函数,如not . null
和isUpper . head . reverse
,然后进行操作{ {1}}他们的结果。
根据@ dfeuer的评论,我只想附上以下解决方案以获得更好的性能。您不需要导入除(&&)
Data.Char