因此,我正在尝试编写一个函数,该函数给定两个整数列表,将每个列表的第i个偶数相加,然后将它们返回到另一个列表中。如果列表中的一个没有第i个偶数,则考虑为0。例如,如果列表是[1,2,1,4,6]和[2,2],则返回[4,6,6]([2 + 2,4 + 2,6 + 0])。我有以下代码:
addEven :: [Int] -> [Int] -> [Int]
addEeven [] [] = []
addEeven (x:xs) [] = filter (\g -> g `mod`2 == 0) (x:xs)
addEven [] (y:ys) = filter (\g -> g `mod` 2 == 0) (y:ys)
addEven (x:xs) (y:ys) = (a + b):(addEven as bs)
where
(a:as) = filter (\g -> g `mod` 2 == 0) (x:xs)
(b:bs) = filter (\g -> g `mod` 2 == 0) (y:ys)
在上一个示例中运行该命令时,我得到:
[4,6*** Exception: ex.hs:(4,1)-(8,101): Non-exhaustive patterns in function addEven
我真的看不到我所缺少的内容,因为它不能与我输入的任何内容一起使用。
答案 0 :(得分:1)
filter
可能会消除元素,因此filter (\g -> g
mod 2 == 0)
不能返回任何元素,因此模式(a:as)
和(b:bs)
可能会失败
话虽这么说,我认为您在这里使问题变得太复杂了。您可以首先定义一个辅助函数,以添加列表的两个元素:
addList :: Num a => [a] -> [a] -> [a]
addList (x:xs) (y:ys) = (x+y) : addList xs ys
addList xs [] = xs
addList [] ys = ys
然后,我们对两个参数进行过滤,并制作一个类似于以下内容的函数addEven
:
addEven :: Integral a => [a] -> [a] -> [a]
addEven xs ys = addList (filter even xs) (filter even ys)
或使用on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
:
import Data.Function(on)
addEven :: Integral a => [a] -> [a] -> [a]
addEven = addList `on` filter even
答案 1 :(得分:0)
虽然在这种情况下使用filter
是非常本能的,但也许两次使用filter
然后对结果进行汇总对于大型列表可能效率不高。为什么我们不立即做所有工作以进行更改。?
addMatches :: [Int] -> [Int] -> [Int]
addMatches [] [] = []
addMatches [] ys = filter even ys
addMatches xs [] = filter even xs
addMatches xs ys = first [] xs ys
where
first :: [Int] -> [Int] -> [Int] -> [Int]
first rs [] ys = rs ++ filter even ys
first rs (x:xs) ys = rs ++ if even x then second [x] xs ys
else first [] xs ys
second :: [Int] -> [Int] -> [Int] -> [Int]
second [r] xs [] = [r] ++ filter even xs
second [r] xs (y:ys) = if even y then first [r+y] xs ys
else second [r] xs ys
λ> addMatches [1,2,1,4,6] [2,2]
[4,6,6]