【问题标题】:Elegant way to mask-merge two strings in Haskell在 Haskell 中掩码合并两个字符串的优雅方法
【发布时间】:2022-01-14 18:14:15
【问题描述】:

例如,如果我们有两个字符串 "abc""1234" 我想要结果 "abc4" (第一个字符串掩盖第二个)。 (如果我们将它们垂直绘制,就像波浪来自左侧并轻触字符)

             "a"  "1"            "a"
 wave ->     "b"  "2"   result   "b" 
             "c"  "3"            "c"
                  "4"            "4"  

我从 Haskell 这个解决方案开始

slice from to xs = take (to - from + 1) (drop from xs)
merge l1 l2 = if length l2 > length l1 
                then l1 ++ slice (length l1) (length l2) l2 
                else l1

能否请您提供一些更优雅\紧凑的解决方案。

【问题讨论】:

    标签: list haskell merge


    【解决方案1】:

    你只需要一个特殊的合并函数

    > let merge [] ys = ys
    |     merge xs [] = xs
    |     merge (x:xs) (y:ys) = x : merge xs ys
    

    或使用drop

    > let merge2 x y = x ++ drop (length x) y
    

    【讨论】:

      【解决方案2】:

      你想要一种“zipLongest”,而transpose 是这样的:

      maskMerge1 :: [b] -> [b] -> [b]
      maskMerge1 as bs  =  map head $ transpose [as,bs]
                    -- or:
                    --        head <$> transpose [as,bs]
      

      这非常紧凑和优雅(非常感谢 @leftaroundabout 的 cmets!)。

      从上面看,

          [ "abc" ,        [ ['a' ,'b' ,'c'     ] ,
            "1234" ]         ['1' ,'2' ,'3' ,'4'] ]
          ----------      --------------------------
                           [  "a1","b2","c3","4"  ]   -- transpose
          ----------      --------------------------
            "abc4"         [  'a' ,'b' ,'c' ,'4'  ]   -- map head
      

      另一个答案中带有length 的代码也可以工作,即使是无限的x,尽管调用了可怕的length,但它会将整个x 保留在内存中,因为调用了length 就可以了。

      【讨论】:

      • 这实际上是我更喜欢head 而不是take 的少数情况之一。由于transpose 从不生成空的列列表,head &lt;$&gt; transpose [as,bs] 应该是安全的。我不喜欢这里的&gt;&gt;=,因为它掩盖了保留位置的事实。 (如果由于某种原因应该出现空列,那么head 将以更明显、可调试的方式失败。)
      • @leftaroundabout 有趣且有效的观察,谢谢。使用take 1 而不是head 现在已经成为我的第二天性,但当然head 在这里安全是这段代码的重点。 :) 回复 &gt;&gt;=,它是 concatMap 的缩写,因为 OP 要求提供“紧凑”代码;而concatMap 本身就是map (take 1) &gt;&gt;&gt; concat 的缩写;保留map 确实会让人不言而喻,里面没有空列表,concat 是最初的[ , ] 的对应物。
      • 糟糕,concat 是因为 take 1。多么尴尬。 :)
      猜你喜欢
      • 1970-01-01
      • 2011-04-25
      • 2020-03-29
      • 2016-03-04
      • 1970-01-01
      • 2014-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多