List Ocaml:如何从列表中删除所有重复的元素?

List Ocaml:如何从列表中删除所有重复的元素?,list,duplicates,ocaml,List,Duplicates,Ocaml,在学习Ocaml时,我看到了一段代码,它可以从列表中删除重复的元素 let rec remove = function | [] -> [] | x::[] -> x::[] | x::y::tl -> if x=y then remove (y::tl) else x::remove (y::tl) 然而,我发现这段代码只删除了连续的重复项,所以如果我尝试一些单独出现的重复项,例如[6;6;8;9;4;2;5;1;5;2;3

在学习Ocaml时,我看到了一段代码,它可以从列表中删除重复的元素

let rec remove =
function
  | []       -> []
  | x::[]    -> x::[]
  | x::y::tl ->
     if x=y then remove (y::tl)
     else x::remove (y::tl)
然而,我发现这段代码只删除了连续的重复项,所以如果我尝试一些单独出现的重复项,例如[6;6;8;9;4;2;5;1;5;2;3],代码处理的是具有连续重复项的6,而不是分开的2或5

我怎样才能完全使列表只有唯一的元素? 类似于删除[6;6;8;9;4;2;5;1;5;2;3]->[6;8;9;4;2;5;1;3]

p、 我设法删除了第一个出现的重复项,但我不知道如何删除后面出现的重复项。

我终于想出了办法。 在没有排序的情况下,我使用了元素检查和元素删除功能,这样我就可以检查列表的尾部是否有重复的head,并在删除尾部中的重复项后决定追加head和tail。使主函数成为递归函数,它最终会在不改变顺序的情况下删除所有重复项(并保留第一个重复项)
谢谢你,glennsl。

根据你的描述,你编写了算法的二次版本。 还有一个O(n log n)版本,使用一组已经看到的值:

let remove_duplicates (type a) (l: a list) =
  let module S = Set.Make(struct type t = a let compare = compare end) in
  let rec remove acc seen_set = function
      | [] -> List.rev acc
      | a :: rest when S.mem a seen_set -> remove acc seen_set rest
      | a :: rest -> remove (a::acc) (S.add a seen_set) rest in
  remove [] S.empty l

(上面的代码使用多态比较,您可能希望在实际代码中提供一个比较函数参数)

只需先对其排序即可。然后,所有重复项都将彼此相邻。排序可以是一个关键,但此时我想要的是在不更改任何元素顺序的情况下删除。无论如何,排序是一个很好的主意,然后你必须跟踪到目前为止遇到的每个元素,并检查每个连续的元素。Hashtbl将把这降到O(n)。作为一个小的改进,你可以先删除尾部的重复项,然后再检查头部是否已经存在。虽然这将保留每个元素的最后一次出现,而不是第一次出现。