簡體   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