我试图从Data.List中实现单词函数,但我的实现并没有完全按照我的意愿工作。
例如,如果函数的输入是 "tere vana kere",那么输出是["vana", "kere"],并且漏掉了第一个单词。但是当我在输入 "tere vana kere "前面加上空格时,输出是正确的["tere", "vana", "kere"]。
谁能指出这个问题。谢谢您
words' :: String -> [String]
words' xs = snd $ foldr (\x acc -> if isSpace x then
if null (fst acc) then
acc
else
([], (fst acc): (snd acc))
else
(x:fst acc, snd acc)
) ([],[]) xs
好了,我们来试试这个。
step x acc =
if isSpace x
then
if null (fst acc)
then acc
else ([], (fst acc) : (snd acc))
else (x : fst acc, snd acc)
words' xs = snd $ foldr step ([], []) xs
现在让我们一步一步的来演练一下: 假设我们要 words' "ABC DEF GHI"
. 我们可以这样做。
Prelude> step 'I' ([], [])
("I", [])
Prelude> step 'H' it
("HI", [])
Prelude> step 'G' it
("GHI", [])
Prelude> step ' ' it
("", ["GHI"])
Prelude> step 'F' it
("F", ["GHI"])
Prelude> step 'E' it
("EF", ["GHI"])
Prelude> step 'D' it
("DEF", ["GHI"])
Prelude> step ' ' it
("", ["DEF","GHI"])
Prelude> step 'C' it
("C", ["DEF","GHI"])
Prelude> step 'B' it
("BC", ["DEF","GHI"])
Prelude> step 'A' it
("ABC", ["DEF","GHI"])
Prelude> snd it
["DEF","GHI"]
你看到这里的问题了吗?
问题是,只有当你看到一个空格字符时,你才会将当前的单词 "刷新 "到单词列表中。特别是,你 不要 当你看到输入端时,就会刷新。你可以通过替换 snd
:
words' xs = (\ (w, ws) -> w:ws) $ foldr step ([], []) xs
顺便说一下,恭喜你让代码正确处理了多个连续的空格。 :-)
EDIT: 为了保留这个好的属性
words' xs = (\ (w, ws) -> if null w then ws else w:ws) $ ...
关于上面的回答: 与其在字符串的末尾用单独的检查来刷新当前的单词, 为什么不在字符串的开头加上一个空格.
step x acc =
if isSpace x
then
if null (fst acc)
then acc
else ([], (fst acc) : (snd acc))
else (x : fst acc, snd acc)
words' xs = snd $ foldr step ([], []) $ ' ':xs