Haskell:从字符串列表中删除空格

4
问题是:编写一个函数,从字符串中删除前导空格。 示例:cutWhitespace [" x","y"," z"] 预期结果:["x","y","z"] 这是我拥有的代码:
cutWhitespace (x:xs) = filter (\xs -> (xs /=' ')) x:xs

当输入为[" x"," y", " z"]时,此函数返回["x", " y", " z"]。为什么它会忽略第二个和第三个字符串中的空格?如何进行修复?
我们可以使用高阶函数,这就是为什么我实现了filter。

3
你的函数是仅删除字符串中的前导空格,还是删除字符串数组中每个元素的前导空格?如果是后者,你可以使用map(dropWhile(\c -> c == ' '))。 - Marc Talbot
2
你只把空格 ' ' 视为空白字符吗?那制表符、换行符等呢?通常正则表达式将空白字符视为空格、换行符、制表符、回车符、垂直制表符和换页符。 - Willem Van Onsem
你询问如何从单个字符串中删除前导空格,但是你的示例是从字符串列表中删除前导空格。你想要做哪一个? - Paul Johnson
3个回答

6

OP的cutWhitespace函数只能作用于第一个字符串的原因是,由于运算符优先级,实际上它只是这个函数:

cutWhitespace (x:xs) = (filter (\xs -> (xs /=' ')) x) : xs

这里我用括号将大部分内容框起来,以便清楚地展示它的求值过程。筛选器只应用于x,而x是输入列表的第一个元素;在示例输入" x"中。

如果按照给定的方式筛选" x",你会得到"x"

Prelude> filter (\xs -> (xs /=' ')) " x"
"x"

因此,cutWhitespace最后一步是将列表的其余部分([" y", " z"])与"x"连接在一起,以返回["x"," y"," z"]

为了解决这个问题,您可以编写函数,并意识到字符串列表是字符的嵌套列表,即[[Char]]

需要注意的是,在模式匹配(x:xs)时如果没有同时匹配上[],可能会出现问题,因为空列表会导致匹配失败。


1
使用dropWhile是完成此操作的最佳方式,使用filter会很麻烦,比使用dropWhile更加困难。感谢您的帮助,您的解释非常有用! - Alowishious

2
您所询问的问题是如何从字符串中删除前导空格,您可以通过对字符串执行dropWhile来实现:
deleteLeadingWhitespace = dropWhile (\c -> c == ' ')

如果你考虑其他的“空格”情况,那么你应该更聪明一些。例如,你可以使用Data.Char中定义的“isSpace”函数。

从你的样本数据来看,似乎你真正想为一个字符串列表做这件事,这种情况下,你可以将dropWhile映射到你的数组上:

map deleteLeadingWhitespace

您采用的过滤器方法有些危险,因为即使它按照您的预期工作,它也会删除所有空格,而不仅仅是前导空格。

5
第二个例子不应该是map deleteLeadingWhitespace吗? - Cirdec
绝对应该。已修复! - Marc Talbot

2

不要编写自定义函数来检查字符是否为空格,建议使用isSpace :: Char -> Bool。这个函数不仅对于空格(' ')返回True,还对于换行符('\n')、回车符('\r')、制表符('\t')、垂直制表符('\v')和换页符('\f')也会返回True。通常使用这样的函数更好,因为遗漏某些情况的可能性更低。

因此,我们可以使用以下代码从单个字符串中删除空格:

dropWhile isSpace

我们可以使用dropWhile函数以过滤掉所有isSpace字符。

然后,我们可以对此过滤器执行映射操作,以过滤掉所有字符串中的空格,如下所示:

import Data.Char(isSpace)

cutWhitespace = map (dropWhile isSpace)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接