如何在 ocaml 中一次遍历两个列表?
How to iterate over two lists at once in ocaml?
假设我有以下两个列表:
让 a = [1;2;3;4];;
让 b = [1;3;5;7];;
我想要第三个列表,其中包含 a 和 b 的索引总和; IE
让 c = [2;5;8;11];;
问题是我如何仅使用 List.fold_right、List.fold_left and/or List.map 中的函数来执行此操作? (这是一道作业题,所以我不允许使用递归函数或@。)
map2
函数执行此操作:
let c = List.map2 (fun i j -> i+j) a b;;
既然是作业题,实在只能提示一下了。
假设您想使用 List.map
。 List.map
的类型是 ('a -> 'b) -> 'a list -> 'b list
。换句话说,它适用于一个列表。如果你想用它来解决你的问题,你必须找到你自己的方法将你的两个列表组合成一个列表。您不能使用 List.map
来执行此操作,并且无论您对列表进行什么操作,都可能会为您执行添加操作。所以这看起来不太乐观。
现在假设您想使用 List.fold_left
。 List.fold_left
的类型是('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
。折叠的伟大之处在于它允许您携带 'a
类型的任意累积状态。它允许您在处理列表时对该累积状态执行任意修改。
在我看来,您可以将其中一个列表视为此累积状态的一部分,因为您可以折叠处理另一个列表。
(* 与 fold_left 和 @ *)
let (_,c)=
List.fold_left( fun (iPos,la) ia ->
(iPos+1,la@[ia+List.nth b iPos])
) (0,[]) a ;;
(* 有 fold_left 没有 @ 但 rev *)
let (_,c)=
List.fold_left( fun (iPos,la) ia ->
(iPos-1,ia+List.nth b iPos::la)
) (List.length b-1,[]) (List.rev a);;
(* 有 fold_left 没有 @ *)
let (_,c)=
List.fold_left( fun (iPos,la) _ ->
(iPos-1,List.nth a iPos+List.nth b iPos::la)
) (List.length b-1,[]) a
(* 与 fold_right *)
let (_,c)=
List.fold_right( fun ia (iPos,la) ->
(iPos-1,ia+List.nth b iPos::la)
) a (List.length b-1,[]) ;;
(* 附地图 *)
let c=
let riPos=ref (-1) in
List.map ( fun ia ->
riPos := !riPos+1;
ia+List.nth b !riPos
) a ;;
(* 使用 mapi *)
let c=
List.mapi ( fun iPos ia ->
ia+List.nth b iPos
) a ;;
(* 使用 map2 *)
let c=List.map2 (+) a b;;
假设我有以下两个列表: 让 a = [1;2;3;4];; 让 b = [1;3;5;7];; 我想要第三个列表,其中包含 a 和 b 的索引总和; IE 让 c = [2;5;8;11];;
问题是我如何仅使用 List.fold_right、List.fold_left and/or List.map 中的函数来执行此操作? (这是一道作业题,所以我不允许使用递归函数或@。)
map2
函数执行此操作:
let c = List.map2 (fun i j -> i+j) a b;;
既然是作业题,实在只能提示一下了。
假设您想使用 List.map
。 List.map
的类型是 ('a -> 'b) -> 'a list -> 'b list
。换句话说,它适用于一个列表。如果你想用它来解决你的问题,你必须找到你自己的方法将你的两个列表组合成一个列表。您不能使用 List.map
来执行此操作,并且无论您对列表进行什么操作,都可能会为您执行添加操作。所以这看起来不太乐观。
现在假设您想使用 List.fold_left
。 List.fold_left
的类型是('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
。折叠的伟大之处在于它允许您携带 'a
类型的任意累积状态。它允许您在处理列表时对该累积状态执行任意修改。
在我看来,您可以将其中一个列表视为此累积状态的一部分,因为您可以折叠处理另一个列表。
(* 与 fold_left 和 @ *)
let (_,c)=
List.fold_left( fun (iPos,la) ia ->
(iPos+1,la@[ia+List.nth b iPos])
) (0,[]) a ;;
(* 有 fold_left 没有 @ 但 rev *)
let (_,c)=
List.fold_left( fun (iPos,la) ia ->
(iPos-1,ia+List.nth b iPos::la)
) (List.length b-1,[]) (List.rev a);;
(* 有 fold_left 没有 @ *)
let (_,c)=
List.fold_left( fun (iPos,la) _ ->
(iPos-1,List.nth a iPos+List.nth b iPos::la)
) (List.length b-1,[]) a
(* 与 fold_right *)
let (_,c)=
List.fold_right( fun ia (iPos,la) ->
(iPos-1,ia+List.nth b iPos::la)
) a (List.length b-1,[]) ;;
(* 附地图 *)
let c=
let riPos=ref (-1) in
List.map ( fun ia ->
riPos := !riPos+1;
ia+List.nth b !riPos
) a ;;
(* 使用 mapi *)
let c=
List.mapi ( fun iPos ia ->
ia+List.nth b iPos
) a ;;
(* 使用 map2 *)
let c=List.map2 (+) a b;;