Zip with default value instead of dropping values?

后端 未结 9 775
夕颜
夕颜 2020-12-01 18:30

I\'m looking for a function in haskell to zip two lists that may vary in length.
All zip functions I could find just drop all values of a lists that is longer than the o

相关标签:
9条回答
  • 2020-12-01 19:11

    You can append an inifinte list of 0 or 1 to each list and then take the number you need from the result zipped list:

    zipWithDefault :: a -> b -> [a] -> [b] -> [(a,b)]
    zipWithDefault da db la lb = let len = max (length la) (length lb)
                                     la' = la ++ (repeat da)
                                     lb' = lb ++ (repeat db)
                                 in take len $ zip la' lb'  
    
    0 讨论(0)
  • 2020-12-01 19:11

    As you said yourself, the standard zip :: [a] -> [b] -> [(a, b)] drops elements from the longer list. To amend for this fact you can modify your input before giving it to zip. First you will have to find out which list is the shorter one (most likely, using length). E.g.,

    zip' x xs y ys | length xs <= length ys  =  ...
                   | otherwise               =  ...
    

    where x is the default value for shorter xs and y the default value for shorter ys.

    Then you extend the shorter list with the desired default elements (enough to account for the additional elements of the other list). A neat trick for doing so without having to know the length of the longer list is to use the function repeat :: a -> [a] that repeats its argument infinitely often.

    zip' x xs y ys | length xs <= length ys = zip {-do something with xs-} ys
                   | otherwise              = zip xs {-do something with ys-}
    
    0 讨论(0)
  • 2020-12-01 19:18

    Yet another implementation:

    zipWithDefault :: a -> b -> (a -> b -> c) -> [a] -> [b] -> [c]
    zipWithDefault dx _  f []     ys     = zipWith f (repeat dx) ys
    zipWithDefault _  dy f xs     []     = zipWith f xs (repeat dy)
    zipWithDefault dx dy f (x:xs) (y:ys) = f x y : zipWithDefault dx dy f xs ys
    

    And also:

    zipDefault :: a -> b -> [a] -> [b] -> [c]
    zipDefault dx dy = zipWithDefault dx dy (,)
    
    0 讨论(0)
提交回复
热议问题