Intersection of two lists in OCaml
List intersection is a simple operation that is often needed, unfortunately, it is not implemeted directly in OCaml (at least, in 4.12). Note that with large collections, sets are a better container for intersections. However, when you know you are working with a limited number of items and that performance should not be an issue, it is perfectly fine to intersect lists.
The following one liner will do the job:
let intersection l1 l2 = List.filter (fun e -> List.mem e l2) l1
That’s it. ````List.mem``` makes sure that an element is a __mem__ber of a list, and we filter according to this condition.
You can test it in the toplevel! I recommend using it for these simple functions. It does not replace a proper unit testing, but if you are working quickly on a prototype, nobody will blame you ;)
# let intersection l1 l2 = List.filter (fun e -> List.mem e l2) l1 ;;
val intersection : 'a list -> 'a list -> 'a list = <fun>
# intersection [1;2;3] [4] ;;
- : int list = []
# intersection [1;2;3] [1] ;;
- : int list = [1]
Intersection of a list of list
Let’s leverage the ````fold_left``` function ! It makes sense to define the intersection of a single list as the list itself.
let lists_intersection lists = match lists with
| [] -> []
| [h] -> h
| h::t -> List.fold_left intersection h t
And we can test it quickly as well:
# let lists_intersection lists = match lists with
| [] -> []
| [h] -> h
| h::t -> List.fold_left intersection h t ;;
val lists_intersection : 'a list list -> 'a list = <fun>
# lists_intersection [[1;2;3]; [1]];;
- : int list = [1]
# lists_intersection [[1;2;3]; [1;2]; [1;2]];;
- : int list = [1; 2]
It works!