OCaml:从列表中删除重复项,同时保持右侧的顺序

lit*_*019 5 ocaml

我刚读了这个帖子,觉得很有趣。

remove from the left在几分钟内实现了这个功能:

(*
 * remove duplicate from left:
 * 1 2 1 3 2 4 5 -> 1 2 3 4 5
 * *)
let rem_from_left lst =
  let rec is_member n mlst =
    match mlst with
    | [] -> false
    | h::tl ->
        begin
          if h=n then true
          else is_member n tl
        end
  in
  let rec loop lbuf rbuf =
    match rbuf with
    | [] -> lbuf
    | h::tl ->
        begin
          if is_member h lbuf then loop lbuf tl
          else loop (h::lbuf) rbuf
        end
  in
  List.rev (loop [] lst)
Run Code Online (Sandbox Code Playgroud)

我知道我可以实施is_memberbyMaphashtable使其更快,但此刻这不是我关心的问题。

在实施 的情况下remove from the right,我可以通过List.rev以下方式实施:

(*
 * remove duplicate from right:
 * 1 2 1 3 2 4 5 -> 1 3 2 4 5
 * *)
let rem_from_right lst =
  List.rev (rem_from_left (List.rev lst))
Run Code Online (Sandbox Code Playgroud)

我想知道我们是否可以以其他方式实现它?

Aad*_*hah 5

这就是我将实施的方式remove_from_right

let uniq_cons x xs = if List.mem x xs then xs else x :: xs

let remove_from_right xs = List.fold_right uniq_cons xs []
Run Code Online (Sandbox Code Playgroud)

同样,您可以remove_from_left按如下方式实现:

let cons_uniq xs x = if List.mem x xs then xs else x :: xs

let remove_from_left xs = List.rev (List.fold_left cons_uniq [] xs)
Run Code Online (Sandbox Code Playgroud)

两者各有优缺点:

  1. 虽然List.fold_left是尾递归并占用恒定空间,但它以相反的顺序折叠列表。因此,您需要List.rev结果。
  2. 虽然List.fold_right不需要跟在 a 之后,List.rev但它需要线性空间而不是常量空间来产生结果。

希望有帮助。


zw3*_*324 0

您可以在返回的过程中收集值,而不是在递归到最后的过程中累积值:

let rem_from_right lst =
  let rec is_member n mlst =
    match mlst with
    | [] -> false
    | h::tl ->
        begin
          if h=n then true
          else is_member n tl
        end
  in
  let rec loop lbuf =
    match lbuf with
    | [] -> []
    | h::tl ->
        begin
        let rbuf = loop tl
        in
          if is_member h rbuf then rbuf
          else h::rbuf
        end
  in
  loop lst
Run Code Online (Sandbox Code Playgroud)

  • @AaditMShah我同意,但似乎哲学不同 - “折叠”绝对是现实世界中的方法,但我宁愿把它留给OP稍后发现,而我认为这会很好地说明这种对OP的递归。 (2认同)