Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何压缩不同长度的列表?_Haskell - Fatal编程技术网

Haskell 如何压缩不同长度的列表?

Haskell 如何压缩不同长度的列表?,haskell,Haskell,我怎样才能zip像这样的两个列表 ["Line1","Line2","Line3"] ["Line4","Line5"] 不丢弃第一个列表中的rest元素 如果可以的话,我想用空列表压缩额外的元素 zipWithPadding :: a -> b -> [a] -> [b] -> [(a,b)] zipWithPadding a b (x:xs) (y:ys) = (x,y) : zipWithPadding a b xs ys zipWithPadding a _ [

我怎样才能
zip
像这样的两个列表

["Line1","Line2","Line3"]
["Line4","Line5"]
不丢弃第一个列表中的rest元素

如果可以的话,我想用空列表压缩额外的元素

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)
只要有元素,我们就可以简单地压缩它们。一旦元素用完,我们就用一个无限的padding元素列表来压缩剩余的列表

在您的情况下,您可以将此用作

zipWithPadding "" "" ["Line1","Line2","Line3"] ["Line4","Line5"]
-- result: [("Line1","Line4"),("Line2","Line5"),("Line3","")]

另一个解决方案是创建一个zip函数,该函数在幺半群上工作,并用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","")]

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

如果你是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)    

有时候我不想填我的清单。例如,当我只想压缩等长列表时。这里是一个通用的解决方案,如果一个列表更长,它可能会返回任何额外的值

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
这只是对齐塔人方法的阐述。然后将该函数实现为(使用{-#语言元组{-}):


好吧,如果你不丢弃它们,你还能做什么?把短名单填上?如果是,使用什么值?我编辑我的问题。如果在
zip
之后会出现类似
(“string”,[])
zip list的重复元素a$list\u b++repeat”“@Riccardo我不认为这更好,在不一定有
Monoid的情况下,公认的答案会起作用,并且可能希望对不同的拉链使用不同的默认值。数据可能对
没有好的意义,但仍然会有一个健全的
内存(或多个健全的默认值)。Haskell的最佳实践是使用尽可能少的限制类型,使用
Monoid
对该函数的限制超出了必要的范围,因为没有使用
。此外
mzip
可以通过将
mempty
传递给这两个默认值来定义
zipWithPadding
。@Riccardo我个人认为,如果标准库定义了
class Default m where mempty::m
class Default m=>Monoid m where mappend::m->m->m
@Riccardo:
mzip=zipWithPadding mempty mempty
。仅仅因为某些东西使用了
Monoid
并不能使它更好或更强大;)。我看我的评论肯定太短了,不能不被误解,让我澄清一下:)我同意这样一个事实,
zipWithPadding
解决方案更一般,毫无疑问。但是问题是关于字符串列表的,因为OP明确要求使用
填充。在这方面,涉及幺半群的解决方案不仅对于OP来说足够一般,而且比必须指定两个不会改变的默认参数更简单。这就是我最喜欢
mempty
解决方案的原因。看起来有人已经在
数据默认值中实现了
Default
类。您可以使用签名
(默认a,默认b)=>[a]->[b]->[(a,b)]
编写
mzip
,并用
def
替换
mempty
。它已经有许多常见类型的实例,因此如果我已经依赖于该包,那么在这种情况下我将选择它。请注意那些想要查看
mempty
Monoid
的人:
zipWithPadding mempty mempty
将为您提供
(monoidA,monoidB)=>[a]->[b]->[(a,b)]
zipWithPadding a b as bs = zipWithOr (,) (,b) (a,) as bs