Return 一个列表,其中包含一对元素,但前提是各个元素的总和为奇数

Return a list, which contains a pair of elements, but only if the respective elements' sums are odd

Implement the oddPairs :: [Int] -> [Int] -> [(Int, Int)] function that returns a list of pairs, but only if the parameters' lists' respective elements' sums are odd.

For example:

oddPairs [1,2,3] [2,2,2] == [(1,2),(3,2)]

oddPairs [1,3,5] [2,4,6] == zip [1,3,5] [2,4,6]

oddPairs [1,2,3] [1,2,3] == []

到目前为止,我已经试过了

oddPairs (x:xs) (y:ys) | (x+y) `mod` 2 == 0 = []
                       | (x+y) `mod` 2 /= 0 = [(x, y)] ++ oddPairs (xs) (ys)

在第一个示例中,它 returns 仅 [(1,2)],在第二个示例中,它 returns 是正确的值,但有一个 Non-exhaustive patterns 错误。

如果两个项目是偶数,你不应该只是return一个空列表,而是继续递归直到至少一个列表被耗尽,所以:

oddPairs :: Integral a => [a] -> [a] -> [(a, a)]
oddPairs [] _ = []
oddPairs _ [] = []
oddPairs (x:xs) (y:ys)
    -- keep searching for new items ↓
    | (x+y) `mod` 2 == 0 = <strong>oddPairs xs ys</strong>
    | otherwise = (x, y) : oddPairs xs ys

另一种看待问题的方法是,您只希望 的总和为奇数。这是重点上的细微差别,可能会导致以下内容。

使用zip函数将每个列表组合成。然后用filter求和为奇数的

oddPairs :: Integral a => [a] -> [a] -> [(a, a)]
oddPairs f s = filter oddPair (zip f s)
    where oddPair (l, r) = not $ even (l + r)

通过列表理解非常简单:

oddPairs :: [Int] -> [Int] -> [(Int, Int)]
oddPairs ms ns = [(m, n) | (m, n) <- zip ms ns, odd (m + n)]

确实:

> oddPairs [1, 2, 3] [2, 2, 2] == [(1, 2),(3, 2)]
True
> oddPairs [1, 3, 5] [2, 4, 6] == zip [1, 3, 5] [2, 4, 6]
True
> oddPairs [1, 2, 3] [1, 2, 3] == []
True