我试图从Data.List实现word函数,但是我的实现无法完全按照我的期望进行。

例如,如果函数的输入为“ 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


顺便说一句,恭喜您使代码正确处理了多个连续的空格。 :-)

编辑:要保留该不错的属性:

words' xs = (\ (w, ws) -> if null w then ws else w:ws) $ ...

08-16 06:44