实现
populationBelow :: Int -> [(String, Int)] -> [String]
函数,该函数返回给定表中人口(百万)小于参数中给定数字的国家名称。例如:
populationBelow 10 [ ("Hungary", 9.773),
("Japan", 126.8),
("Iceland", 0.3604),
("United States", 327.2),
("Mongolia", 3.076)
] == ["Hungary", "Iceland", "Mongolia"]
populationBelow 0 [ ("Hungary", 9.773),
("Japan", 126.8),
("Iceland", 0.3604),
("United States", 327.2),
("Mongolia", 3.076)] == []
到目前为止,我已经试过了:
populationBelow x ((y, z):ys) | z < x = [y] ++ populationBelow x (ys)
| otherwise = (y) : populationBelow x (ys)
对于小数不起作用,如果表中包含多个满足条件的元素,则会得到Non-exhaustive patterns
错误。
populationBelow :: RealFrac a => a -> [(String, a)] -> [String]
populationBelow _ [] = []
populationBelow x ((y, z):ys)
| z < x = y : populationBelow x ys
| otherwise = populationBelow x ys
当前代码有几个问题:
- 空列表的基本情况(因此会出现非穷举模式错误),无论它是由于递归而耗尽还是一开始就是空的,都缺失了。
- 无论条件的结果如何,您都将
y
添加到结果中。在第一种情况下通过连接,第二种情况是通过将其添加到递归调用结果的头部。y
只有在其总体低于给定阈值时才应加入。 - 你的函数提供的签名表明它只使用整数,但输入示例有十进制数。我已更改签名以接受十进制数字。
你绝对是在正确的轨道上。为了能够处理小数,您应该使类型签名更通用一些。而且,相当直接的过滤任务可以被认为是最优雅的列表推导式:
populationBelow :: Ord b => b -> [(a, b)] -> [a]
populationBelow k xs = [x | (x, n) <- xs, n < k]
确实:
> populationBelow 10 [("Hungary", 9.773), ("Japan", 126.8), ("Iceland", 0.3604), ("United States", 327.2), ("Mongolia", 3.076)]
["Hungary","Iceland","Mongolia"]