在 OCaml 中将 `('a list * b' list) list` 扁平化为 `'a list* 'b list` 的函数
Function to flatten `('a list * b' list) list` to `'a list* 'b list` in OCaml
我需要 OCaml 中的一个函数,它将采用一种类型
('a list * b' list) list
创造它
'a list * b' list
。我尝试使用内置函数 List.flatten 和 List.concat 但它们不起作用,它们需要一种类型 'c list list
。有人可以帮助我吗?
您可以像这样使用函数 fold_left
来完成它:
您从两个用作累加器的空列表开始。对于输入列表中的每个 sub-lists,您将元素添加到相应的累加器中(第一个 sub-list 的元素在第一个累加器中,第二个 sub-list 的元素相同)。
# let flatten l =
let (l1,l2) =
List.fold_left (fun (l1,l2) (x,y) ->
(x :: l1, y :: l2)) ([], []) l in
List.rev (List.flatten l1), List.rev (List.flatten l2);;
val flatten : ('a list * 'b list) list -> 'a list * 'b list = <fun>
#
以下应该有效:
let split2 l = (List.map fst l, List.map snd l)
let flatten2' (l1, l2) = (List.flatten l1, List.flatten l2)
let flatten2 l = flatten2' (split2 l)
这里,split2
会把一个('a list * 'b list) list
变成一个('a list list * 'b list list)
(fst
和snd
return的第一个和第二个组成部分一对)和 flatten2'
将分别展平这两个组件。 flatten2
最终会完成您的要求。你也可以把它打包成一个函数,但我觉得这样更容易理解。
注意List.map
和List.flatten
都不是tail-recursive;如果你需要 tail-recursive 版本,还有其他库有它们,或者你可以使用 rev_xxx
函数从标准库构建它们或从头开始编写它们。
您必须使用函数 List.split
和 List.flatten
:
let my_function l =
let (fst_list, snd_list) = List.split l in
List.flatten fst_list, List.flatten snd_list ;;
首先,split
函数将生成 'a list list
和一个 'b list list
,然后您只需 flatten
它们。
不幸的是,没有元组映射,您需要分解 - 例如使用拆分和展平:
let splcat x = match List.split x with | (a,b) -> (List.flatten a, List.flatten b) ;;
这就是它在命令行上的样子:
utop # splcat [([1;2],["a"]); ([3],["uvw";"xyz"]) ] ;;
- : int list * bytes list = ([1; 2; 3], ["a"; "uvw"; "xyz"])
我需要 OCaml 中的一个函数,它将采用一种类型
('a list * b' list) list
创造它
'a list * b' list
。我尝试使用内置函数 List.flatten 和 List.concat 但它们不起作用,它们需要一种类型 'c list list
。有人可以帮助我吗?
您可以像这样使用函数 fold_left
来完成它:
您从两个用作累加器的空列表开始。对于输入列表中的每个 sub-lists,您将元素添加到相应的累加器中(第一个 sub-list 的元素在第一个累加器中,第二个 sub-list 的元素相同)。
# let flatten l =
let (l1,l2) =
List.fold_left (fun (l1,l2) (x,y) ->
(x :: l1, y :: l2)) ([], []) l in
List.rev (List.flatten l1), List.rev (List.flatten l2);;
val flatten : ('a list * 'b list) list -> 'a list * 'b list = <fun>
#
以下应该有效:
let split2 l = (List.map fst l, List.map snd l)
let flatten2' (l1, l2) = (List.flatten l1, List.flatten l2)
let flatten2 l = flatten2' (split2 l)
这里,split2
会把一个('a list * 'b list) list
变成一个('a list list * 'b list list)
(fst
和snd
return的第一个和第二个组成部分一对)和 flatten2'
将分别展平这两个组件。 flatten2
最终会完成您的要求。你也可以把它打包成一个函数,但我觉得这样更容易理解。
注意List.map
和List.flatten
都不是tail-recursive;如果你需要 tail-recursive 版本,还有其他库有它们,或者你可以使用 rev_xxx
函数从标准库构建它们或从头开始编写它们。
您必须使用函数 List.split
和 List.flatten
:
let my_function l =
let (fst_list, snd_list) = List.split l in
List.flatten fst_list, List.flatten snd_list ;;
首先,split
函数将生成 'a list list
和一个 'b list list
,然后您只需 flatten
它们。
不幸的是,没有元组映射,您需要分解 - 例如使用拆分和展平:
let splcat x = match List.split x with | (a,b) -> (List.flatten a, List.flatten b) ;;
这就是它在命令行上的样子:
utop # splcat [([1;2],["a"]); ([3],["uvw";"xyz"]) ] ;;
- : int list * bytes list = ([1; 2; 3], ["a"; "uvw"; "xyz"])