Haskell - 使用toUpper将列表[String]中的所有字母大写

Joh*_*ohn 2 haskell list map filter toupper

我有一个列表[String]任务是删除列表中的那些元素,它们有"q"或"p",然后用toUpper大写列表中的所有字母.

我尝试的是如下:

delAndUpper :: [String] -> [String]
delAndUpper myList = filter (\x -> not('p' `elem` x || 'q' `elem` x)) myList
Run Code Online (Sandbox Code Playgroud)

它正确地从列表中删除了不需要的元素,但由于toUpper的类型是Char,因此无法在此列表中应用toUpper.

我用地图试了一下它不起作用.

delAndUpper myList = map toUpper (filter (\x -> not('p' `elem` x || 'q' `elem` x)) myList)
Run Code Online (Sandbox Code Playgroud)

我知道,在这行代码中,toUpper获取一个列表作为值,因此它无法工作,但知道如何进入列表并将应用映射到上层.

请你帮助我好吗.

提前致谢!

问候

And*_*ewC 8

更深层次地映射一级

你需要使用map (map toUpper).

这是因为你有[String]而不是String.

toUpper           :: Char -> Char
map toUpper       :: [Char] -> [Char]
Run Code Online (Sandbox Code Playgroud)

map toUpper       :: String -> String
map (map toUpper) :: [String] -> [String]
Run Code Online (Sandbox Code Playgroud)

map toUpper通过使每个字母为大写来大写map (map toUpper)字符串,因此大写字符串列表中的每个字符串.

你的功能变了

delAndUpper myList = map (map toUpper) (filter (\x -> not('p' `elem` x || 'q' `elem` x)) myList)
Run Code Online (Sandbox Code Playgroud)

dave4420提出了一个很好的建议,这(map.map) toUpper是一种简洁的写作方式map (map toUpper),可以帮助你简单而自然地思考两个列表级别 - 看看他的答案.

我们可以解除p和q的硬连线吗?

你问是否有更短的方法来编写条件,并且不喜欢硬编码`q``p`.我同意那些多位`elem`不漂亮.让我们在不允许的字母列表中传递并整理一下:

delAndUpper omit strings = map (map toUpper) (filter ok strings) where
            ok xs = not (any (`elem` omit) xs)
Run Code Online (Sandbox Code Playgroud)

这里(`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
Run Code Online (Sandbox Code Playgroud)

从中我们可以删除尾随的xs:

ok = ((not.).any) (`elem` omit) 
Run Code Online (Sandbox Code Playgroud)

和内联:

delAndUpper omit strings = map (map toUpper) (filter (((not.).any) (`elem` omit)) strings)
Run Code Online (Sandbox Code Playgroud)

我也不热衷于落后strings:

delAndUpper omit = map (map toUpper).filter (((not.).any) (`elem` omit))
Run Code Online (Sandbox Code Playgroud)

(我们也可以摆脱这个omit争论并完全免费获得,但在我难以理解的道路上,这将会走得太远了.)

哪个Q?

> delAndUpper "pq" $ words "The Queen has probably never had a parking ticket."
["THE","QUEEN","HAS","NEVER","HAD","A","TICKET."]
Run Code Online (Sandbox Code Playgroud)

这是必需的行为吗?仔细排除小写变体然后将所有内容都设为大写似乎很奇怪.我们可以反过来这样做:

upperAndDel omit = filter (((not.).any) (`elem` omit)).map (map toUpper)
Run Code Online (Sandbox Code Playgroud)

> upperAndDel "PQ" $ words "The Queen has probably never had a parking ticket."
["THE","HAS","NEVER","HAD","A","TICKET."]
Run Code Online (Sandbox Code Playgroud)