【问题标题】:Sum corresponding elements of two lists, with the extra elements of the longer list added at the end将两个列表的对应元素相加,将较长列表的额外元素添加到末尾
【发布时间】:2020-11-19 01:55:35
【问题描述】:

我正在尝试将两个列表添加在一起并保留未使用的额外元素并将它们添加到新列表中,例如

  • addLists [1,2,3] [1,3,5,7,9] = [2,5,8,7,9]

到目前为止我有这个:

addLists :: Num a => [a] -> [a] -> [a]
addLists xs ys = zipWith (+) xs ys

但不确定如何将多余的元素添加到新列表中。

下一步是将其更改为采用组合函数的高阶函数 作为论据:

longZip :: (a -> a -> a) -> [a] -> [a] -> [a]

【问题讨论】:

  • 看看zipWith是如何实现的,并使用显式递归。
  • 我坚持如何编写显式递归部分@WillemVanOnsem

标签: list haskell


【解决方案1】:

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]implemented as [src]

zipWith :: (a->b->c) -> [a]->[b]->[c]
zipWith f = go
  where
    go [] _ = []
    go _ [] = []
    go (x:xs) (y:ys) = f x y : go xs ys

因此它使用显式递归,其中go 将检查两个列表是否为非空,在这种情况下产生f x y,否则它会停止并返回一个空列表[]

您可以实现zipWith 的变体,即使其中一个列表为空,它也会继续。这看起来像:

zipLongest :: (a -> a -> a) -> [a] -> [a] -> [a]
zipLongest f = go
  where go [] ys = …
        go xs [] = …
        go (x:xs) (y:ys) = f x y : go xs ys

还需要填写的地方。

【讨论】:

    【解决方案2】:

    你可以用简单的高阶函数来做到这一点

    import Data.List (transpose)
    
    addLists :: Num a => [a] -> [a] -> [a]
    addLists xs ys = map sum . transpose $ [xs, ys]
    

    因为transpose[xs, ys, ...] 的长度是其参数列表中最长列表的长度,而sum :: (Foldable t, Num a) => t a -> a 已经定义为对列表的元素求和(因为列表是Foldable)。

    transpose 在这里用作zip 的一种(但切割最长的列表而不是最短的列表),其中[] 是列表添加++ 的默认元素,如0是数字加法的默认元素+

    cutLongest [xs, ys] $
      zipWith (++) (map pure xs ++ repeat []) (map pure ys ++ repeat [])
    

    另见:

    【讨论】:

      【解决方案3】:

      您正在寻找the semialign package。它为您提供了类似压缩的操作,但会一直持续到两个列表都用完为止。它还泛化到列表以外的类型,例如rose trees。在您的情况下,您可以这样使用它:

      import Data.Semialign
      import Data.These
      
      addLists :: (Semialign f, Num a) => f a -> f a -> f a
      addLists = alignWith (mergeThese (+))
      
      longZip :: Semialign f => (a -> a -> a) -> f a -> f a -> f a
      longZip = alignWith . mergeThese
      

      新的类型签名是可选的。如果您愿意,您可以继续使用将它们限制在列表中的旧版本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-25
        • 2019-04-06
        • 2023-03-21
        • 2023-01-12
        相关资源
        最近更新 更多