将矩阵的列递归求和到单行(使用 zipWith (+))
Recursive sum columns of matrix to single row (with zipWith (+))
lstsAdder :: [[Integer]] -> [Integer]
lstsAdder [] = []
lstsAdder (x:xs) = zipWith (+) x (lstsAdder xs)
正如标题所说,我希望它递归地添加这个:[[a,b,c],[d,e,f]]
像这样:[a+d,b+e,c+f]
,以及任何有限长度的列表列表。但是我所有的实现 returns 都是 []
。为什么会这样,我该如何解决?
您的基本情况太基本了...该函数将递归地消耗所有行。当它一直沿着递归堆栈向下移动时,它只剩下空列表,即没有行的列表。这 returns 一个空结果。
但是,返回递归堆栈,每一层都应该用 +
压缩到它上面。好吧,但是用空列表压缩任何列表都会导致空列表!
您可以通过三种方式解决此问题:
为单行矩阵添加一个额外的基本情况。如果只有一行,结果应该是只有那一行,对吗?
lstsAdder [] = []
lstsAdder [r] = r
lstsAdder (x:xs) = zipWith (+) x $ lstsAdder xs
在压缩步骤中用零填充缺失的元素。
lstsAdder [] = []
lstsAdder (x:xs) = x ^+^ lstsAdder xs
infixrl 6 ^+^
(^+^) :: [a] -> [a] -> [a]
xs^+^[] = xs
[]^+^ys = ys
(x:xs)^+^(y:ys) = (x+y) : (xs^+^ys)
给出基本情况的无限零列表:
lstsAdder [] = repeat 0
lstsAdder (x:xs) = zipWith (+) x $ lstsAdder xs
您的递归基本情况 returns []
和 length (zipWith f a b) = min (length a) (length b)
。这意味着您的结果将始终具有长度 0。min
的标识元素是 +infinity,(+)
的标识元素是 0
,因此一种可能的基本情况是 repeat 0
.
您还可以查看数据的先决条件是否允许您执行类似
的操作
import Data.List (transpose)
lstsAdder = map sum . transpose
它有不同的边缘情况行为(QuickCheck
给出 [[0,0],[0]]
作为一个示例输入)但也许这些边缘情况在实践中不会发生。
我相信你也可以用一个foldr1
操作做如下;
listsAdd :: (Foldable t, Num c) => t [c] -> [c]
listsAdd = foldr1 (zipWith (+))
*Main> listsAdd [[1,2,3],[4,5,6]]
[5,7,9]
lstsAdder :: [[Integer]] -> [Integer]
lstsAdder [] = []
lstsAdder (x:xs) = zipWith (+) x (lstsAdder xs)
正如标题所说,我希望它递归地添加这个:[[a,b,c],[d,e,f]]
像这样:[a+d,b+e,c+f]
,以及任何有限长度的列表列表。但是我所有的实现 returns 都是 []
。为什么会这样,我该如何解决?
您的基本情况太基本了...该函数将递归地消耗所有行。当它一直沿着递归堆栈向下移动时,它只剩下空列表,即没有行的列表。这 returns 一个空结果。
但是,返回递归堆栈,每一层都应该用 +
压缩到它上面。好吧,但是用空列表压缩任何列表都会导致空列表!
您可以通过三种方式解决此问题:
为单行矩阵添加一个额外的基本情况。如果只有一行,结果应该是只有那一行,对吗?
lstsAdder [] = [] lstsAdder [r] = r lstsAdder (x:xs) = zipWith (+) x $ lstsAdder xs
在压缩步骤中用零填充缺失的元素。
lstsAdder [] = [] lstsAdder (x:xs) = x ^+^ lstsAdder xs infixrl 6 ^+^ (^+^) :: [a] -> [a] -> [a] xs^+^[] = xs []^+^ys = ys (x:xs)^+^(y:ys) = (x+y) : (xs^+^ys)
给出基本情况的无限零列表:
lstsAdder [] = repeat 0 lstsAdder (x:xs) = zipWith (+) x $ lstsAdder xs
您的递归基本情况 returns []
和 length (zipWith f a b) = min (length a) (length b)
。这意味着您的结果将始终具有长度 0。min
的标识元素是 +infinity,(+)
的标识元素是 0
,因此一种可能的基本情况是 repeat 0
.
您还可以查看数据的先决条件是否允许您执行类似
的操作import Data.List (transpose)
lstsAdder = map sum . transpose
它有不同的边缘情况行为(QuickCheck
给出 [[0,0],[0]]
作为一个示例输入)但也许这些边缘情况在实践中不会发生。
我相信你也可以用一个foldr1
操作做如下;
listsAdd :: (Foldable t, Num c) => t [c] -> [c]
listsAdd = foldr1 (zipWith (+))
*Main> listsAdd [[1,2,3],[4,5,6]]
[5,7,9]