繁体   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