我在完成这个问题时遇到问题。任何可能的解决方案的提示将不胜感激。
给定一个Double
值v
和一个Double
值列表xs
,calcList
返回一个Double
根据以下规则:
-
对于
xs
中x
的每个值,如果x
不为正,则输出列表中将没有相应的值。 -
否则,相应的输出值将
x * ln x
。 -
但是,当且仅当其值大于
v
时,此值才会出现在输出列表中。 -
相应输出值(如果存在(的顺序应与输入相同值。
以下是一些示例:
calcList 1.0 [] = []
calcList 1.0 [3.0] = [3.2958]
calcList 1.0 [-1.0, 1.0, 3.0, 5.0, 7.0, 9.0] = [3.2958, 8.0472, 13.6214, 19.7750]
calcList 100.0 [1.0 .. 40.0] = [102.0359, 106.4536, 110.9035, 115.3847, 119.8963, 124.4372, 129.0067, 133.6040, 138.2283, 142.8789, 147.5552]
到目前为止,我拥有的:
positive :: Double -> Bool
positive x = x > 0.0
calcValue :: Double -> Double
calcValue x = log x * x
calcList :: Double -> [Double] -> [Double]
calcList v xs = []
calcList v xs
所以看起来有 3 个步骤。
- 去除元素 <= 0 (
filter
( - 将每个剩余元素乘以其自然对数(
map
( - 摆脱元素 <=
v
(filter
(
我们可以使用 (.)
(自 f.g == x -> f (g x)
以来(来组合函数,而不是将这些分别应用于输入。
calcList = v -> filter (>v) . map (x -> x*log x) . filter (>0)
您应该查看filter
和map
上的文档。此外,《学习你一个哈斯克尔》中的这一章将是一个很好的阅读。
我们可以使用一种方法,其中我们使用filter
,和 map
。可以通过列表理解获得等效的解决方案:
calcList :: (Ord d, Floating d) => d -> [d] -> [d]
calcList v xs = [xlogx | x <- xs, x > 0, let xlogx = x * log x, xlogx > v]
因此,我们在这里使用x <- xs
来迭代xs
中的元素,通过使用x > 0
我们过滤值,以便只考虑x > 0
的值。接下来我们将变量xlogx
定义为 let xlogx = x * log x
,然后我们有一个额外的过滤器来检查是否xlogx > v
。
列表推导式的 yield 部分(管道字符 |
之前的部分(指定我们将xlogx
添加到列表中。
另一种方法是
calcList :: Double -> [Double] -> [Double]
calcList v [] = []
calcList v (x:xs) = case (positive x) of {
False -> calcList v xs;
True -> case ((calcValue x) > v) of {
False -> calcList v xs;
True -> (calcValue x):(calcList v xs);
};
}
在每个cases
中,您检查其中一个条件,并在列表开头添加数字,以便顺序相同。