我正在尝试创建一个函数,该函数查找在给定的排序列表中有多少元素大于第一个元素除以2
的元素。例如,给定列表[3,3,4,5,6,7,8,9,11]
,第一个元素是3
,数字大于2
的数字为7,8,9,11
,因此函数返回4
。
到目前为止我已经完成了这项工作,但它不起作用。 a
元素是列表中的第一个元素,为了方便起见而给出。
fun findlarger a [] =
| findlarger [] = 0
| findlarger [x] = 0
| findlarger (x::xs) =
let
val a = ref a;
in
if !a < x/2 then length (xs) + 1 else findlarger (a, xs)
end
答案 0 :(得分:3)
我甚至不知道从哪里开始指出代码问题。您似乎误解了函数式编程的基础知识。
"<"
不是sml中的严格小于运算符。正如你在那里写的那样,它是一个字符串。 修复原始代码会产生类似的结果。请注意,第一个元素总是放回到列表中,以便我们知道要与之比较的内容。
fun findlarger [] = 0
| findlarger [x] = 0
| findlarger (x::y::xs) =
if y > x*2 then
1 + findlarger(x :: xs)
else
findlarger(x :: xs)
然而,您也可以使用内部辅助函数并完成x * 2的计算,因此每次都不会计算
fun findlarger [] = 0
| findlarger (x::xs) =
let
val xx = 2*x
fun f [] = 0
| f (y::ys) =
(if y > xx then 1 else 0) + f ys
in
f xs
end
如果使用其他答案中建议的高阶函数,则应避免遍历列表两次(首先筛选出元素,然后计算剩余的元素)。您应该只浏览一次列表,并计算与给定谓词匹配的元素 要完成此功能,您可以使用折叠功能之一。在大多数情况下,使用foldl是有意义的,因为它将以尾递归的方式从左到右遍历列表。
fun p (x, y) = if y > 2*x then 1 else 0
fun f [] = 0
| f (x::xs) = foldl (fn (a,b) => b + p(x, a)) 0 xs
答案 1 :(得分:2)
试试这个解决方案:
fun find lst =
case lst of
[] => 0
| x::_ => List.length(List.filter(fn e => e > 2 * x) lst)
用法:
find [3,3,4,5,6,7,8,9,11] => 4