繁体   English   中英

在Clean中将字符串拆分为字符串列表

[英]Split string to a list of strings in Clean

由于资源有限,我需要在这里提出一个问题。 我一直在努力进行函数式编程,无休止的Haskell教程并没有真正帮助我。 因此,我要用Clean语言实现的目标是将" car cow cat "类的字符串拆分为字符串列表["car","cow","cat"] 您能为我提供一个详细的答案(不一定是完整的代码),有关如何遍历此字符串,尤其是将新构造的字符串添加到列表中的部分吗?

我将提供一个简单的解决方案。 在Haskell中,有无限多种更好的方法可以做到这一点,但这是我想到的最简单的函数式编程方法,而无需使用任何特定的Haskell函数(例如takeWhile或什至没有折叠和贴图)。

您基本上想模拟对列表的迭代,所以这是我的建议:

  1. 定义一个将使用字符串和分隔符的函数。 此函数将返回字符串列表spliton :: String -> Char -> [String]

  2. 要移至列表上方,我们将要吞噬字符,直到我们击中分割字符之一。 我们还将要保存到目前为止保存的单词以及整个单词列表。 为此,我们将定义一个子函数来保存状态

    spliton' :: String -> Char -> String -> [String] -> [String]

    spliton' [] _ sofar res = res ++ [sofar]

    我还包括了最简单的子句-空字符串。 当我们的字符串为空时,我们只想返回到目前为止保存的内容。

  3. 现在,让我们继续进行实际的递归函数:如果我们击中分隔符,我们将到目前为止保存的字符串添加到列表中,并以空的当前状态字符串重新开始。如果我们未击中分隔符,我们将字符添加到当前状态字符串

     spliton' (currchar:rest) splitby sofar res | currchar==splitby = spliton' rest splitby "" (res++[sofar]) | otherwise = spliton' rest splitby (sofar++[currchar]) res 

因此,总结一下我们的代码:

spliton :: String -> Char -> [String]
spliton source splitchar = spliton' source splitchar [] []

spliton' :: String -> Char -> String -> [String] -> [String]
spliton' [] _ sofar res = res ++ [sofar]
spliton' (currchar:rest) splitby sofar res
         | currchar==splitby = spliton' rest splitby "" (res++[sofar])
         | otherwise = spliton' rest splitby (sofar++[currchar]) res

注意:但是,这不会摆脱空字符串-这意味着如果您有很多多余的空格-您会将它们添加到列表中。 我会让您考虑如何处理该案件-希望这可以帮助您入门。

让我们将其分为几个子问题:

  1. 列出字符串中的字符,以便我们可以轻松地应用模式匹配。
  2. 刮擦列表的初始部分(尽可能只使用空格或不使用空格),并且仅在不使用空格时保留它。
  3. 列表为非空时,请重复第二步。

第一件事可以使用fromString完成。 对于第二步和第三步,我们定义一个辅助函数:

scrape :: [Char] -> [String]
scrape [] = []
scrape cs=:[c:_]
| isSpace c = scrape (dropWhile isSpace cs)
| otherwise = [toString word:scrape rest]
where
    (word,rest) = span (not o isSpace) cs

第一种选择是匹配空列表的基本情况。 第二种选择将整个列表cs与第一个元素c相匹配。 如果第一个字符是空格,则我们递归地(第3步)在同一列表上调用相同的函数,而没有空格的起始部分。 如果第一个字符不是空格,则使用span :: (a -> Bool) [a] -> ([a], [a])将列表拆分成单词的开头部分,其余部分。 我们使用toString作为字符串存储单词,然后对列表的其余部分递归调用scrape

现在,我们只需要一个包装即可使它成为类型为String -> [String]的函数:

split :: String -> [String]
split s = scrape (fromString s)
where
    scrape :: [Char] -> [String]
    scrape [] = []
    scrape cs=:[c:_]
    | isSpace c = scrape (dropWhile isSpace cs)
    | otherwise = [toString word:scrape rest]
    where
        (word,rest) = span (not o isSpace) cs

请注意,您可以通过传递字符d并将isSpace c替换为c == d并将(not o isSpace)((<>) d)来轻松地从定界符中抽象出来。 另外,您可以选择不传递字符d而是选择函数isDelim :: Char -> Bool 然后,分别获得isDelim c(not o isDelim)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM