映射更深一层
你需要使用map (map toUpper)
.
这是因为你有[String]
而不是String
.
toUpper :: Char -> Char
map toUpper :: [Char] -> [Char]
IE
map toUpper :: String -> String
map (map toUpper) :: [String] -> [String]
map toUpper
通过使每个字母大写来将字符串大写,因此map (map toUpper)
将字符串列表中的每个字符串大写。
你的功能变成
delAndUpper myList = map (map toUpper) (filter (\x -> not('p' `elem` x || 'q' `elem` x)) myList)
dave4420 提出了一个很好的建议,这(map.map) toUpper
是一种简洁的写作方式map (map toUpper)
,可以帮助您非常简单自然地思考两个列表级别 - 也请查看他的答案。
我们可以取消对 p 和 q 的硬连线吗?
您问是否有更短的方法来编写条件,并且不喜欢硬编码`q`
and `p`
。我同意那些多位`elem`
并不漂亮。让我们传入不允许的字母列表并整理一下:
delAndUpper omit strings = map (map toUpper) (filter ok strings) where
ok xs = not (any (`elem` omit) xs)
这里(`elem` omit)
检查一个字符是否在会导致我们省略该单词的字符列表中,因此(any (`elem` omit) xs)
检查是否有任何字符xs
被禁止。当然,如果没有禁止,那就是ok
.
您的原件delAndUpper
现在是delAndUpper "pq"
,或者如果您还想禁止大写 P 和 Q,delAndUpper "pqPQ"
。(稍后会详细介绍。)
我们可以让它更简洁吗?
让我们看看我们能不能写得ok
更短一点。我的第一个想法是使用pointfree
它(有关如何使其在 ghci 中运行的详细信息,请参阅我对另一个问题的回答not
),但它似乎挂起,因此使用一些标准的转换技巧,我们可以组合一个带有两个参数的函数在给我们一个 Bool 之前,(not.).f
而不是not.f
像我们在第一次输入后给我们一个 Bool 的函数那样做。any
是(`elem` omit)
作为它的第一个论点。这给了我们
ok xs = ((not.).any) (`elem` omit) xs
我们可以从中删除尾随的 xs:
ok = ((not.).any) (`elem` omit)
和内联:
delAndUpper omit strings = map (map toUpper) (filter (((not.).any) (`elem` omit)) strings)
我也不热衷于尾随strings
:
delAndUpper omit = map (map toUpper).filter (((not.).any) (`elem` omit))
(我们也可以摆脱omit
争论,完全没有意义,但这在我看来很难阅读的道路上走得太远了。)
Q去哪儿?
> delAndUpper "pq" $ words "The Queen has probably never had a parking ticket."
["THE","QUEEN","HAS","NEVER","HAD","A","TICKET."]
这是必需的行为吗?小心地排除小写变体然后将所有内容变为大写似乎很奇怪。我们可以反过来做:
upperAndDel omit = filter (((not.).any) (`elem` omit)).map (map toUpper)
给予
> upperAndDel "PQ" $ words "The Queen has probably never had a parking ticket."
["THE","HAS","NEVER","HAD","A","TICKET."]