如何在列表推导式中用模式匹配实现字符串首字母大写其余小写
现有代码问题说明
你写的列表推导式存在两处核心问题:
- 语法错误:
head` word的反引号使用错误,反引号仅用来把二元函数转为中缀写法,head是一元函数,直接写head word即可 - 逻辑错误:列表推导的卫语句位置只能放返回布尔值的表达式,用来过滤参与计算的元素,
head word返回的是字符类型,不符合卫语句的类型要求,自然无法运行。
问题解答
1. 能不能用列表推导实现需求?
可以,思路是给每个字符配上索引,区分第一个元素和其余元素的处理逻辑,示例代码如下:
import Data.Char (toUpper, toLower) capitalize :: String -> String capitalize word = [if idx == 0 then toUpper c else toLower c | (idx, c) <- zip [0..] word]
但这种实现方式不如模式匹配直观,性能也没有优势,更推荐用模式匹配拆分字符串(字符串本质是[Char]类型的列表,天然支持头/尾拆分的模式匹配):
import Data.Char (toUpper, toLower) capitalize :: String -> String capitalize [] = [] -- 匹配空串边界情况 capitalize (headChar:restChars) = toUpper headChar : map toLower restChars
2. 同一位置能不能设置多个卫语句?
可以,多个卫语句之间用逗号分隔,只有所有卫语句都返回True时才会执行对应逻辑。如果你需要判断首字符是否为字母再做转换,可以直接在模式匹配后加卫语句,示例如下(首字符非字母时保留原样,其余字符统一转小写):
import Data.Char (toUpper, toLower, isAlpha) capitalize :: String -> String capitalize [] = [] capitalize (headChar:restChars) | isAlpha headChar = toUpper headChar : map toLower restChars | otherwise = headChar : map toLower restChars
如果你要在列表推导里保留非字母字符、仅对字母做大小写转换,不要把isAlpha放在卫语句位置(会过滤掉非字母字符),放在元素处理的条件分支里即可:
import Data.Char (toUpper, toLower, isAlpha) capitalize :: String -> String capitalize word = [ if idx == 0 && isAlpha c then toUpper c else if isAlpha c then toLower c else c | (idx, c) <- zip [0..] word ]
内容的提问来源于stack exchange,提问作者idontknowhowtocode
相关产品推荐
相关产品推荐

