如果值超过特定阈值,则列表中的双精度元素

时间:2014-11-11 15:55:45

标签: haskell functional-programming

尝试将列表中大于5的元素加倍。

将列表中的每个元素加倍,我会这样做

doubleAll n = [2*x| x <-n]

现在我想使用列表推导将列表中所有大于5的元素加倍。 所以,如果我这样做

doubleAll n = [2*x| x <-n, x>5]

我的清单[1,2,3,4,5]会导致[10]。但我希望我的清单显示[1,2,3,4,10]

任何人都可以解释我做错了什么以及如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

[2*x| x <-n, x>5]的解释是:

  1. n获取下一个元素并将其命名为x
  2. 如果x>5继续,否则转到第1步
  3. 返回值2*x作为列表的下一个元素。
  4. 重复
  5. 很明显,x>5过滤了n的元素。表达式相当于:

    map (\x -> 2*x) ( filter (\x -> x>5) n )
    

    Arthur所述,您需要以下内容:

    [ if x > 5 then 2*x else x | x <- n ]
    

    它的解释是:

    1. 获取n的下一个值,并将其命名为x
    2. 返回值if x > 5 then 2*x else x作为列表的下一个值。

答案 1 :(得分:0)

如果您不使用列表推导并使用mapfilter操作,则可以更清楚地理解:

-- Apply a function to every element of the list.
map :: (a -> b) -> [a] -> [b]

-- Throw out list elements that don't pass the test.
filter :: (a -> Bool) -> [a] -> [a]

您的原始doubleAll与此相同:

-- Multiply every element of the list by two.
doubleAll xs = map (*2) xs

仅当x > 5为此时才加倍的版本:

-- Apply the `step` function to every element of the list.  This step function 
-- multiplies by two if x >= 5, otherwise it just returns its argument.
doubleAll xs = map step xs
    where step x | x >= 5    = 2*x
                 | otherwise = x

您编写的列表推导版本的问题是它等同于此:

-- Filter out list elements that are smaller than 5, then double the remaining ones.
doubleAll xs = map (*2) (filter (>=5) xs)

产生所需结果的列表推导解决方案将改为:

doubleAll xs = [if x >= 5 then x*2 else x | x <- xs]

作为一个更一般的评论,我总是建议新手远离列表理解并学习更高阶列表功能,这些功能更通用,更不神奇。