【问题标题】:Haskell: Merging a list where even indices are from list 1 and odd are from list 2. Fill with 0's if not the same sizeHaskell:合并一个列表,其中偶数索引来自列表 1,奇数索引来自列表 2。如果大小不同,则填充 0
【发布时间】:2020-03-20 14:47:33
【问题描述】:

我尝试创建一个 Haskell 函数,它将 2 个列表合并到一个列表中,其中新列表中的偶数索引来自列表 1,奇数索引来自列表 2。如果大小不同,请填充 0。

例如:

[1] [10,15,20] => [1,10,0,15,0,20] 
[2,3] [4,5] => [2,4,3,5]

我尝试创建几个版本,但都没有成功。

我怎样才能创造出这样的东西?

【问题讨论】:

标签: list haskell zero-padding


【解决方案1】:

使用我的this answer 的想法,使用transpose :: [[a]] -> [[a]] 函数,

interweaveWith :: a -> [a] -> [a] -> [a]
interweaveWith def xs ys =
   -- 0 [1] [10,15,20] => [1,10,0,15,0,20] 
   concat $
      zipWith const
         (transpose [ xs ++ repeat def,      -- no limit, padded with def
                      ys ++ repeat def ])
         (transpose [xs, ys])                -- as long as the longest

【讨论】:

    【解决方案2】:

    有一个interleave 函数,它做了类似的事情,但不完全是这样。它“合并”列表,直到其中一个结束。

    所以你可以自己写那个函数:

    merge :: [Int] -> [Int] -> [Int]
    merge (x:xs) (y:ys) = x : y : merge xs ys
    merge (x:xs) [] = x : 0 : merge xs []
    merge [] (y:ys) = 0 : y : merge [] ys
    merge _ _ = []
    

    当我们在两边都有一些元素时,我们把它们都取走。当其中一个元素不存在时,我们取 0 代替它。在所有其他情况下(它是 merge [] [] 情况),我们以递归结束并返回一个空列表。

    我们还可以稍微概括一下我们的函数以支持任何类似数字的类型:

    merge :: Num a => [a] -> [a] -> [a]
    merge (x:xs) (y:ys) = x : y : merge xs ys
    merge (x:xs) [] = x : 0 : merge xs []
    merge [] (y:ys) = 0 : y : merge [] ys
    merge _ _ = []
    

    此外,我们可以更进一步,使用来自Data.Default 包的def 来获取我们类型的默认值,因此我们不仅可以将这个函数用于数字列表:

    import Data.Default
    
    merge :: Default a => [a] -> [a] -> [a]
    merge (x:xs) (y:ys) = x : y : merge xs ys
    merge (x:xs) [] = x : def : merge xs []
    merge [] (y:ys) = def : y : merge [] ys
    merge _ _ = []
    

    【讨论】:

    • 这就回答了。谢谢!
    猜你喜欢
    • 2019-02-08
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多