【问题标题】:Concatenate List of Strings, adding a separator in between using foldl Haskell连接字符串列表,在使用 foldl Haskell 之间添加分隔符
【发布时间】:2020-03-03 14:13:08
【问题描述】:

我有一个函数,旨在将字符串组合在一个列表中,在每个字符串之间添加一个分隔符,并使用 foldl 输出单个字符串。这是我所拥有的以及该函数的一些预期行为——它不起作用,我不确定为什么。

-- | `sepConcat sep [s1,...,sn]` returns `s1 ++ sep ++ s2 ++ ... ++ sep ++ sn`
--
-- >>> sepConcat "---" []
-- ""
--
-- >>> sepConcat ", " ["foo", "bar", "baz"]
-- "foo, bar, baz"
--
-- >>> sepConcat "#" ["a","b","c","d","e"]
-- "a#b#c#d#e"

sepConcat :: String -> [String] -> String
sepConcat sep []     = ""
sepConcat sep (x:xs) = foldLeft f base l
  where
    f a x            = a ++ sep ++ x
    base             = ""
    l                = xs

【问题讨论】:

    标签: haskell foldleft


    【解决方案1】:

    我认为你可以通过检查第一个参数是否为空字符串并相应地处理它来解决这个问题

    sepConcat sep = foldl (\x y -> if x == "" then y else x ++ sep ++ y) ""
    -- or
    sepConcat sep = foldl combine ""
      where combine "" x = x
            combine x y = x ++ sep ++ y
    
    

    【讨论】:

      【解决方案2】:

      最大的问题是你的模式匹配:

      sepConcat sep []     = ""
      sepConcat sep (x:xs) = foldLeft f base l
      

      您无需在[](x:xs) 中再次划分模式,因为foldlfoldr 可以处理两种情况。这就是 foldl 可以定义为递归列表的方式:

      foldLeft :: (b -> a -> b) -> b -> [a] -> b
      foldLeft f base []     = base
      foldLeft f base (x:xs) = f (foldLeft f base xs) x
      

      你只需要正确地应用这两种情况:

      sepConcat :: String -> [String] -> String
      sepConcat sep xs = foldLeft (\rs s ->
       if null rs 
       then s ++ rs
       else s ++ sep ++ rs) "" xs
      

      这里空列表的情况是"",函数是针对列表的递归情况

      用你的例子:

      sepConcat ", " ["foo", "bar", "baz"]
      => "foo, bar, baz"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-09
        • 1970-01-01
        • 2018-07-15
        • 2012-12-06
        • 2020-06-03
        • 1970-01-01
        • 2019-10-29
        • 2015-11-21
        相关资源
        最近更新 更多