首页 > 解决方案 > 正数递增,负数全部减1

问题描述

声明类型并定义一个函数,该函数接受一个数字列表并返回一个列表,其中所有正数都递增(加一),负数递减(减一)。此外,如果列表中有 0,它将被淘汰。

例如 fun [2, -4, 0, 66, -1] 将返回 [3, -5, 67, -2]

我在两个 filter 和 map 语句和 zipWith (++) 之间尝试过 (++)

这是我的代码,它给出了编译错误。

incDec (x:xs) = map (+1) $ filter (>0) (x:xs) (++)
                map (-1) $ filter (<0) (x:xs)

标签: haskell

解决方案


$将比任何其他运算符绑定得更松,因此您需要显式括号。此外,您不需要解构列表,因为您只是将其重新组合在一起(该x:xs模式是不必要的,并且会破坏您在空列表上的功能)

incDec xs = (map (+1) $ filter (>0) xs) ++
            (map (subtract 1) $ filter (<0) xs)

(请参阅此处了解我为什么使用subtract而不是- 上面)

但是,这仍然不能满足您的要求。由于您要过滤和映射两次,因此您最终会得到所有开头的正数和结尾的负数,因此您会丢失列表的原始顺序。相反,我们将使用concatMap,它可以用作一种混合过滤器/映射。

incDec :: (Ord a, Num a) => [a] -> [a]
incDec = concatMap go                  -- Do the map / filter combination
    where go x = case x `compare` 0 of -- Compare the number to 0
                   LT -> [x - 1]       -- If negative, subtract one
                   GT -> [x + 1]       -- If positive, add one
                   EQ -> []            -- If zero, eliminate

示例用法:

*Main> incDec [2, -4, 0, 66, -1]
[3,-5,67,-2]

推荐阅读