我正在做一个练习,要求我编写一个函数来大写字符串的所有首字母.
这是我到目前为止所做的:
upperFirst:: String -> String upperFirst str = let upperFirstForEachWord (firstLetter:others) = toUpper firstLetter : map toLower others in unwords (map upperFirstForEachWord (words str))
这就是它的工作原理:
upperFirst "" = "" upperFirst "hello friends!" = "Hello Friends!"
但是也:
upperFirst " " = "" upperFirst " a a a " = "A A A"
由于功能的原因,我在开始时,最后都会丢失白色空格words
.
如何递归保存它们(不处理所有可能的情况)?
感谢您的任何帮助!
words
您不想像提取单词一样,而是只想拆分字符串,这样每个单词的开头也位于列表的开头.正如郝连评论说,这可以做到splitOn
,但标准groupBy
也会做到这一点:
import Data.List import Data.Char upperFirst = concat . map (\(c:cs) -> toUpper c : cs) . groupBy (\a b -> isSpace a == isSpace b)
这是如何工作的:它将所有空格或所有非空格的字符组合在一起.然后它会对每个子字符串的开头进行大写(对于空白来说也是低效的,但无害),然后将所有字符串连接在一起.
正如user3237465所说,组合map
和concat
非常普遍,并且特殊情况更为常见.此外,还有一个很好的小组合器,在用一些谓词进行分组或排序时派上用场.因此你也可以这样写
import Control.Monad import Data.Function upperFirst = groupBy ((==)`on`isSpace) >=> \(c:cs) -> toUpper c : cs
最重要的是,你可以使用时髦的现代修改方式,对于大写部分:
import Control.Lens upperFirst = groupBy ((==)`on`isSpace) >=> ix 0 %~ toUpper