如何在 OCaml 中不使用 List.filter 过滤列表?
How do I filter a list without using List.filter in OCaml?
我必须编写一个函数,给定两个列表,它 return 是第一个元素的列表,其平方出现在第二个列表中(对不起我的英语)。我不能递归地做,我不能使用 List.filter。
这就是我所做的:
let lst1= [1;2;3;4;5];;
let lst2= [9;25;10;4];;
let filquadi lst1 lst2 =
let aux = [] in
List.map(fun x -> if List.mem (x*x) lst2 then x::aux else []) lst1;;
它有效,但当数字不满足 if 语句时它也会打印 []:
filquadi lst1 lst2 ;;
- : int list list = [[]; [2]; [3]; []; [5]]
我怎样才能 return 一个数字列表而不是一个数字列表的列表?
- : int list = [2;3;5]
你可以用List.concat把东西放在最后:
List.concat (List.map ...)
作为旁注,aux
在您的代码中没有做任何有用的事情。它只是空列表的名称(因为 OCaml 变量是不可变的)。使用 [x]
而不是 x :: aux
.
可能会更清楚
作为另一边的评论,这是一个听起来很奇怪的任务。通常禁止使用 List
模块中的函数的原因是鼓励您编写自己的递归解决方案(这确实具有教育意义)。我暂时看不出禁止使用递归的理由,但是以不同的方式组合 List
中的函数很有趣。
您的条件并没有说您不能使用 List.fold_left
或 List.rev
,所以...
let filter lst1 lst2 =
List.fold_left
(fun init x ->
if List.mem (x * x) lst2 then x::init
else init)
[] lst1
|> List.rev
我们从一个空列表开始,当我们折叠第一个列表时,仅当该元素出现在第二个列表中时才添加当前元素。因为这会导致列表与其原始顺序相反,所以我们随后将其反转。
如果您不应该使用递归,这在技术上是作弊,因为 List.fold_left
递归工作,但基本上任何使用列表的工作都是如此。重新实现 List
模块的功能将涉及大量递归,从重新实现 fold_left
和 filter
.
可以看出
let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
let rec filter f lst =
match lst with
| [] -> []
| x::xs when f x -> x :: filter f xs
| _::xs -> filter f xs
我必须编写一个函数,给定两个列表,它 return 是第一个元素的列表,其平方出现在第二个列表中(对不起我的英语)。我不能递归地做,我不能使用 List.filter。 这就是我所做的:
let lst1= [1;2;3;4;5];;
let lst2= [9;25;10;4];;
let filquadi lst1 lst2 =
let aux = [] in
List.map(fun x -> if List.mem (x*x) lst2 then x::aux else []) lst1;;
它有效,但当数字不满足 if 语句时它也会打印 []:
filquadi lst1 lst2 ;;
- : int list list = [[]; [2]; [3]; []; [5]]
我怎样才能 return 一个数字列表而不是一个数字列表的列表?
- : int list = [2;3;5]
你可以用List.concat把东西放在最后:
List.concat (List.map ...)
作为旁注,aux
在您的代码中没有做任何有用的事情。它只是空列表的名称(因为 OCaml 变量是不可变的)。使用 [x]
而不是 x :: aux
.
作为另一边的评论,这是一个听起来很奇怪的任务。通常禁止使用 List
模块中的函数的原因是鼓励您编写自己的递归解决方案(这确实具有教育意义)。我暂时看不出禁止使用递归的理由,但是以不同的方式组合 List
中的函数很有趣。
您的条件并没有说您不能使用 List.fold_left
或 List.rev
,所以...
let filter lst1 lst2 =
List.fold_left
(fun init x ->
if List.mem (x * x) lst2 then x::init
else init)
[] lst1
|> List.rev
我们从一个空列表开始,当我们折叠第一个列表时,仅当该元素出现在第二个列表中时才添加当前元素。因为这会导致列表与其原始顺序相反,所以我们随后将其反转。
如果您不应该使用递归,这在技术上是作弊,因为 List.fold_left
递归工作,但基本上任何使用列表的工作都是如此。重新实现 List
模块的功能将涉及大量递归,从重新实现 fold_left
和 filter
.
let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
let rec filter f lst =
match lst with
| [] -> []
| x::xs when f x -> x :: filter f xs
| _::xs -> filter f xs