簡體   English   中英

如何比較Haskell中同一列表中的多個字符串

[英]How to compare multiple strings within in the same list in Haskell

我正在嘗試編寫一個Haskell函數,它接受一個字符串列表,比較列表中的所有字符串,並輸出一個長度最長的字符串列表。 我想在沒有任何預定義函數或導入的情況下執行此操作,我想嘗試以遞歸方式計算出來。 例如:

    longeststrings["meow","cats","dog","woof"] -> ["meow","cats","woof"]

我知道這是一個愚蠢的例子,但我認為這證明了這一點。

我想做點什么

    longeststrings:: [string] -> [string]
    longeststrings []          = []
    longeststrings [x:xs]      = if (x > xs) x:longeststrings[xs]

但我不知道如何只從列表中取出最大的字符串,或刪除最小的字符串。 我將不勝感激任何幫助。

你可以輕而易舉地跟蹤最長的字符串和一個長度值的累加器。

longestStrings :: [String] -> [String]
longestStrings = go [] 0
  where
  go acc _ []       = acc  -- base case
  go acc n (x:xs)
    | length x > n  = go [x] (length x) xs
    -- if x is longer than the previously-seen longest string, then set
    -- accumulator to the list containing only x, set the longest length
    -- to length x, and keep looking
    | length x == n = go (x:acc) n xs
    -- if x is the same length as the previously-seen longest string, then
    -- add it to the accumulator and keep looking
    | otherwise     = go acc n xs
    -- otherwise, ignore it

或者,正如Davislor在評論中正確提到的那樣,這可以通過教導輔助函數來確定其最長的長度來實現。

longestStrings :: [String] -> [String]
longestStrings = foldr f []
  where
  f x []        = [x]
  f x yss@(y:_) =
    case compare (length x) (length y) of
      GT -> [x]
      EQ -> x : yss
      LT -> yss

根據要求,這是一個使用和不使用where 我認為這是一個很好的證明,為什么建議不要使用where是不好的建議。 我認為第一個版本更容易理解。

請記住,函數式編程不是一個修道院的誓言,可以用受虐狂來釋放某些關鍵詞。 它也不是時尚尖端的清單( where如此的最后一個賽季!)。 “你應該任意避免這種結構,因為它不是'功能'的事情”真的不是它的工作方式。 所以你不應該為了這樣的提示而丑化你的代碼。

它往往遵循同樣的編碼風格為其他程序員所以他們會發現很容易理解,你是個好主意。 (例如,亞當·斯密被巧妙地努力訓練你, acc是蓄能器的通用名稱,並go了遞歸輔助功能的通用名稱,並幫助其他的程序員弄清楚他使用的模式。)但實際上Haskell的程序員確實where很多where使用。

無論如何,代碼:

longeststrings :: [String] -> [String]
{- Filters all strings as long as any other in the list. -}
longeststrings = foldr go []
  where
    go x [] = [x]
    go x leaders | newlength > record  = [x]
                 | newlength == record = x:leaders
                 | otherwise           = leaders
      where
        record = (length . head) leaders
        newlength = length x

longestStringsUsingLambda :: [String] -> [String]
longestStringsUsingLambda = foldr
    (\x leaders ->
       if leaders == [] then [x]
       else case compare (length x) (length $ head leaders) of
         GT -> [x]
         EQ -> x:leaders
         LT -> leaders )
    []

main :: IO ()
main = let testcases = [ ["meow","cats","dog","woof"],
                         ["foo","bar","baz"],
                         ["meep","foo","bar","baz","fritz","frotz"]
                       ]
       in foldMap print $
          map longestStringsUsingLambda testcases

您可以嘗試刪除let testcases = ...並查看您是否認為這是一項改進。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM