Unique elements in a list in OCaml
First, one should note that there is a function List.sort_uniq
which is proposed in OCaml. However, it requires the implementation of a comparison function (like >
for integers of float numbers) and this comparison it not always obvious to implement (think about a list of arrays per example).
Instead, the following snippet will do the job!
Snippet
let unique l =
let rec aux l acc =
match l with
| [] ->
List.rev acc
| h :: t ->
if List.mem h acc then aux t acc else aux t (h :: acc)
in
aux l []
And we can run it in the toplevel:
# let unique l =
let rec aux l acc =
match l with
| [] ->
List.rev acc
| h :: t ->
if List.mem h acc then aux t acc else aux t (h :: acc)
in
aux l [] ;;
val unique : 'a list -> 'a list = <fun>
# unique [1;2;3] ;;
- : int list = [1; 2; 3]
# unique [1;2;3;2;4;1];;
- : int list = [1; 2; 3; 4]
#
Why the List.rev
The List.rev
may be seen as a useless operation. It just makes sure that the elements are returned in their order of first occurence.
In order to be closer to the standard terminology used in the language, one could maybe implement two functions: unique
and stable_uniq
.
let unique l =
let rec aux l acc =
match l with
| [] ->
acc
| h :: t ->
if List.mem h acc then aux t acc else aux t (h :: acc)
in
let stable_unique l =
let rec aux l acc =
match l with
| [] ->
List.rev acc
| h :: t ->
if List.mem h acc then aux t acc else aux t (h :: acc)
in
aux l []
List.mem and List.memq
Note that I used List.mem but you should be aware of the following differences (from the docs):
val mem : ‘a -> ‘a list -> bool
mem a set is true if and only if a is equal to an element of set.
val memq : ‘a -> ‘a list -> bool
Same as List.mem, but uses physical equality instead of structural equality to compare list elements.