List 如何对列表中的每2个元素求和?
基本上,我想执行以下操作: [1,2,3,4,5,6,7]->[3,7,11,7] 在上面的示例中,列表末尾的元素被单独保留,因为列表的长度是奇数,因此无法添加任何元素 我想把这个列表变成一个元组列表,比如[1,2,3,4]->[(1,2),(3,4)],然后对每个元组执行加法,但我不知道怎么做,也不确定它是否可以处理奇数长度的列表List 如何对列表中的每2个元素求和?,list,haskell,List,Haskell,基本上,我想执行以下操作: [1,2,3,4,5,6,7]->[3,7,11,7] 在上面的示例中,列表末尾的元素被单独保留,因为列表的长度是奇数,因此无法添加任何元素 我想把这个列表变成一个元组列表,比如[1,2,3,4]->[(1,2),(3,4)],然后对每个元组执行加法,但我不知道怎么做,也不确定它是否可以处理奇数长度的列表 当然,有一种方法可以将列表中的每两个元素相加。一种简单的方法是通过基本的递归定义: sumPairs :: Num a => [a] -> [a] --
当然,有一种方法可以将列表中的每两个元素相加。一种简单的方法是通过基本的递归定义:
sumPairs :: Num a => [a] -> [a]
-- first, we deal with the base case
sumPairs [] = []
-- next we deal with the odd length list base case
sumPairs [x] = [x]
-- now we can recurse!
sumPairs (x:y:list) = (x+y) : sumPairs list
但是,如果您想通过组合现有函数来实现这一点,您可以在hoogle中搜索[a]->[(a,a)]
()以查看是否存在任何相关函数
不幸的是,似乎没有。如果您想要更具组合性的内容,可以编写以下函数:
pairUp :: Num a => [a] -> [(a,a)]
pairUp [] = []
pairUp [x] = [(x, 0)]
pairUp (x:y:list) = (x,y) : pairUp list
sumPairs :: Num a => [a] -> [a]
sumPairs = map (uncurry (+)) . pairUp
或者,如果你想变得更普通
pairUp :: Monoid a => [a] -> [(a,a)]
pairUp [] = []
pairUp [x] = [(x, mempty)]
pairUp (x:y:list) = (x,y) : pairUp list
mergePairs :: Monoid a => [a] -> [a]
mergePairs = map (uncurry (<>)) . pairUp
甚至
combinePairs :: (a -> a -> a) -> [a] -> [a]
combinePairs _ [] = []
combinePairs _ [x] = [x]
combinePairs _ (x:y:list) = f x y : combinePairs list
sumPairs :: Num a => [a] -> [a]
sumPairs = combinePairs (+)
对于这个问题,我想我应该回到显式递归:
sumPairs :: Num a => [a] -> [a]
sumPairs (x:y:ys) = x+y:sumPairs ys
sumPairs xs = xs
很好也很简单:如果至少有两个元素,将它们相加,然后递归完成其余的工作。否则(意味着有零个或一个元素),只需返回您得到的相同列表。非常简短
map sum . chunksOf 2
那么这里到底发生了什么?我还是Haskell的新手,所以可视化其中一些函数是相当困难的。使用第一个示例,如果我想将函数声明更改为pairs:(Integer->Integer->Integer)->[Integer]->[Integer],而不是求和,请执行(+)、(-)、(*)等操作。我该怎么改变定义呢?没关系,我明白了!我只是将uu与空列表和奇数列表一起传入,然后将f与底格一起传入,然后对递归块执行sumf list。其实很简单!
map sum . chunksOf 2