我如何zip
两个列表如
["Line1","Line2","Line3"]
["Line4","Line5"]
不丢弃第一个列表中的休息元素?
我想用空列表压缩额外的元素,如果可以的话。
答案 0 :(得分:10)
zipWithPadding :: a -> b -> [a] -> [b] -> [(a,b)]
zipWithPadding a b (x:xs) (y:ys) = (x,y) : zipWithPadding a b xs ys
zipWithPadding a _ [] ys = zip (repeat a) ys
zipWithPadding _ b xs [] = zip xs (repeat b)
只要有元素,我们就可以简单地压缩它们。一旦我们用完了元素,我们只需用剩余的填充元素列表压缩剩余的列表。
在您的情况下,您可以将其用作
zipWithPadding "" "" ["Line1","Line2","Line3"] ["Line4","Line5"]
-- result: [("Line1","Line4"),("Line2","Line5"),("Line3","")]
答案 1 :(得分:8)
另一种解决方案是制作一个拉链函数,该函数适用于monoid并使用mempty填充缺失值:
import Data.Monoid
mzip :: (Monoid a, Monoid b) => [a] -> [b] -> [(a, b)]
mzip (a:as) (b:bs) = (a, b) : mzip as bs
mzip [] (b:bs) = (mempty, b) : mzip [] bs
mzip (a:as) [] = (a, mempty) : mzip as []
mzip _ _ = []
> mzip ["Line1","Line2","Line3"] ["Line4","Line5"]
[("Line1","Line4"),("Line2","Line5"),("Line3","")]
答案 2 :(得分:1)
Reite解决方案的另一种实现方式,使用更高阶的功能,只是为了好玩。 :)虽然可能比较慢,因为我猜长度函数需要额外遍历列表。
import Data.Monoid (mempty)
zipPad :: (Monoid a, Monoid b) => [a] -> [b] -> [(a,b)]
zipPad xs ys = take maxLength $ zip (pad xs) (pad ys)
where
maxLength = max (length xs) (length ys)
pad v = v ++ repeat mempty
答案 3 :(得分:1)
我认为如果你是Haskell编程的新手
,对你来说会很简单 zip' :: [String] -> [String] ->[(String,String)]
zip' [][] = []
zip' (x:xs)[] = bmi x : zip' xs []
where bmi x = (x,"")
zip' [](x:xs) = bmi x : zip' [] xs
where bmi x = ("",x)
zip' (x:xs) (y:ys) = bmi x y : zip' xs ys
where bmi x y = (x,y)
答案 4 :(得分:1)
有时候我不想填写我的清单。例如,当我想仅压缩相等长度的列表时。这是一个通用的解决方案,如果一个列表更长,它可能会返回任何额外的值。
zipWithSave :: (a -> b -> c) -> [a] -> [b] -> ([c],Maybe (Either [a] [b]))
zipWithSave f [] [] = ([],Nothing)
zipWithSave f [] bs = ([],Just (Right bs))
zipWithSave f as [] = ([],Just (Left as))
zipWithSave f (a:as) (b:bs) = (f a b : cs , sv)
where (cs, sv) = zipWithSave f as bs
使用(zps,svs) = zipWithSave f as bs
,svs
可以是以下三种情况之一:Just (Left x)
其中来自as
的剩余内容将返回为x
,Just (Right x)
其中返回bs
的遗留物,或等长列表中的Nothing
。
另一个通用目的是为每种情况提供额外的功能。
zipWithOr :: (a -> b -> c) -> (a -> c) -> (b -> c) -> [a] -> [b] -> [c]
zipWithOr _ _ _ [] [] = []
zipWithOr _ _ fb [] bs = map fb bs
zipWithOr _ fa _ as [] = map fa as
zipWithOr f fa fb (a:as) (b:bs) = (f a b) : zipWithOr f fa fb as bs
这只是Zeta方法的详细阐述。然后将该函数实现为(使用{ - #LANGUAGE TupleSections# - }):
zipWithPadding a b as bs = zipWithOr (,) (,b) (a,) as bs