问题是:编写一个删除前导白色的功能
字符串中的空格。示例:cutWhitespace [" x","y"," z"]
预期答案:["x","y","z"]
继承我所拥有的:
cutWhitespace (x:xs) = filter (\xs -> (xs /=' ')) x:xs
当输入为["x", " y"," z"]
时,返回[" x"," y", " z"]
。为什么忽略第二个和第三个字符串中的空格以及如何修复它?
我们被允许使用高阶函数,这就是我实现过滤器的原因。
答案 0 :(得分:5)
OP cutWhitespace
函数仅对第一个字符串起作用的原因是由于运算符优先级,它实际上是这个函数:
cutWhitespace (x:xs) = (filter (\xs -> (xs /=' ')) x) : xs
在这里,我将括号放在身体的大部分周围,以明确它的评估方式。 filter
仅适用于x
,x
是输入列表的第一个元素;在示例输入" x"
中。
如果您按照给定的方式过滤" x"
,则会获得"x"
:
Prelude> filter (\xs -> (xs /=' ')) " x"
"x"
然后,cutWhitespace
做的最后一件事就是取出列表的其余部分([" y", " z"]
),并将其放在"x"
上,以便它返回["x"," y"," z"]
。
为了解决这个问题,您可以编写函数,并认识到字符串列表是一个嵌套的字符列表,即[[Char]]
。
作为警告,(x:xs)
上的模式匹配而不匹配[]
是危险的,因为它会在空列表上失败。
答案 1 :(得分:2)
关于如何从字符串中删除前导空格的问题,您只需在字符串上执行dropWhile即可:
deleteLeadingWhitespace = dropWhile (\c -> c == ' ')
如果你考虑其他事情“空白”,你应该更聪明。例如,您可以使用Data.Char中定义的“isSpace”函数。
从您的示例数据中,您似乎真的想要为字符串列表执行此操作,在这种情况下,您可以将dropWhile映射到数组:
map deleteLeadingWhitespace
你正在采取的过滤方法有点危险,因为即使你按照你认为它应该做的那样,它也会删除所有空格,而不仅仅是前导空格。
答案 2 :(得分:2)
我建议使用isSpace :: Char -> Bool
,而不是编写一个自定义函数来检查字符是否为空格。此函数不仅为空格(True
)返回' '
,而且为新行('\n'
),回车符('\r'
),选项卡({ {1}}),垂直标签('\t'
)和表单Feed('\v'
)。通常最好使用这些功能,因为忘记某些情况的几率较低。
因此我们可以删除单个字符串的间距:
'\f'
我们dropWhile isSpace
以dropWhile
的方式isSpace
。
然后我们可以使用此过滤器执行映射,以过滤所有字符串中的空格,例如:
import Data.Char(isSpace)
cutWhitespace = map (dropWhile isSpace)