在Ocaml中使用fold_left反转列表内的元组

问题描述 投票:0回答:3

lst
成为一个包含元组的列表,我想反转每个元组(元组的顺序需要相同)。例如:

[(a,b);(c,d)] -> [(b,a);(d,c)] 

我知道可以用地图来完成:

List.map (fun (a,b) -> (b,a)) [(1,2);(3,4)];;
- : (int * int) list = [(2, 1); (4, 3)]

但我正在寻找一种方法来实现它

List.fold_left
。我的方法是将列表与
[]
作为累加器进行匹配,将每个反向元组连接在一起,但我不断收到类型错误:

List.fold_left (fun (a,b) -> (b,a)) [] lst;;
list tuples ocaml reverse fold
3个回答
0
投票

List.fold_left
采用三个参数:

  • 'a -> 'b -> 'a
  • 类型的函数
  • 类型为
    'a
  • 的累加器
  • 类型列表
    'b list

您的函数

(fun (a,b) -> (b,a))
缺少一个参数,即累加器,您想要在其上连接反转对

(fun acc (a,b) -> (b,a) :: acc)

0
投票

使用

List.map
似乎是一个自然的选择,因为你可以这样做:

List.map (fun (a, b) -> (b, a)) lst

但是如果你想使用

List.fold_left
那么你需要反转每对,然后将其添加到累加器列表中:

List.fold_left (fun acc (a, b) -> (b, a)::acc) [] lst

由于 Fold_left 采用以下函数签名:

('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
,因此您需要确保您的第一个参数是一个接受累加器列表和单个列表元素(在本例中为元组)的函数,然后返回一个列表。

编辑:@Chris 正确地指出,通过这个解决方案,元组本身的顺序也会翻转。您可以通过用

List.rev
包装函数来解决此问题,或者您可以将元组附加到列表的末尾,而不是使用 cons-ing:

List.fold_left (fun acc (a, b) -> acc@[(b, a)]) [] lst


0
投票

@Lhooq 和 @rithvik 的答案大多都是正确的,但会颠倒结果列表中元组的顺序。

我们需要将结果提供给

List.rev
使用
List.fold_right

# List.fold_left (fun acc (a, b) -> (b, a) :: acc) [] [(1, 2); (3, 4)] 
  |> List.rev;;
- : (int * int) list = [(2, 1); (4, 3)]
# List.fold_right (fun (a, b) acc -> (b, a) :: acc) [(1, 2); (3, 4)] [];;
- : (int * int) list = [(2, 1); (4, 3)]
© www.soinside.com 2019 - 2024. All rights reserved.