Search code examples
listhaskellzero-padding

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 size


i've tried to create a Haskell function that is merging 2 lists into a single list, where even indices in the new list are from list 1 and the odd are from list 2. Fill with 0's if not the same size.

For example:

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

I've tried to create a couple of versions but with no luck.

How can I create such a thing?


Solution

  • There is a interleave function, that does something similar, however, not exactly that. It 'merges' lists until one of them ends.

    So you can write that function by yourself:

    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 _ _ = []
    

    When we have some elements on both sides, we take both of them. When one of elements is absent, we take 0 instead of it. In all other cases (it is the merge [] [] case) we end up with our recursion and return an empty list.

    We can also slightly generalize our function to support any number-like type:

    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 _ _ = []
    

    Also, we can go further and use def from Data.Default package to get the default value for our type, so we can use this function with not only lists of numbers:

    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 _ _ = []