View Category

Define an empty list

Assign the variable "list" to a list with no elements
ocaml
let list = [];;

Define a static list

Define the list [One, Two, Three, Four, Five]
ocaml
let list = [ "One"; "Two"; "Three"; "Four"; "Five" ];;

Join the elements of a list, separated by commas

Given the list [Apple, Banana, Carrot] produce "Apple, Banana, Carrot"
ocaml
let () =
let lst = ["Apple"; "Banana"; "Carrot"] in
let str = String.concat ", " lst in
print_endline str

Join the elements of a list, in correct english

Create a function join that takes a List and produces a string containing an english language concatenation of the list. It should work with the following examples:
join([Apple, Banana, Carrot]) = "Apple, Banana, and Carrot"
join([One, Two]) = "One and Two"
join([Lonely]) = "Lonely"
join([]) = ""
ocaml
let join list =
let rec join' list acc =
match list with
| [] -> ""
| [single] -> single
| one::[two] ->
if acc = "" then one ^ " and " ^ two
else acc ^ one ^ ", and " ^ two
| first::others -> join' others (acc ^ first ^ ", ")
in
join' list ""

Produce the combinations from two lists

Given two lists, produce the list of tuples formed by taking the combinations from the individual lists. E.g. given the letters ["a", "b", "c"] and the numbers [4, 5], produce the list: [["a", 4], ["b", 4], ["c", 4], ["a", 5], ["b", 5], ["c", 5]]
ocaml
let combinations =
let l1 = ["a"; "b"; "c"]
and l2 = [4; 5] in
List.rev (
List.fold_left (fun acc y ->
List.fold_left (fun acc2 x ->
(x, y)::acc2
) acc l1
) [] l2
)

From a List Produce a List of Duplicate Entries

Taking a list:
["andrew", "bob", "chris", "bob"]

Write the code to produce a list of duplicates in the list:
["bob"]
ocaml
let rem v lst =
let rec aux acc = function
| [] -> List.rev acc
| x::xs ->
if compare v x = 0
then aux acc xs
else aux (x::acc) xs
in
aux [] lst

(** in case of a match, returns a list with the duplicate(s) removed *)
let rec mem_rem v lst =
let rec aux acc = function
| [] -> None
| x::xs ->
if compare v x = 0
then Some(List.rev_append acc (rem v xs))
else aux (x::acc) xs
in
aux [] lst

let duplicates lst =
let rec aux acc = function
| [] -> List.rev acc
| x::xs ->
match mem_rem x xs with
| Some ret -> aux (x::acc) ret
| None -> aux acc xs
in
aux [] lst

let () =
let lst = ["andrew"; "bob"; "chris"; "bob"; "mike"; "peter"; "bob"] in
let dup = duplicates lst in
List.iter print_endline dup
(* Using standard (functorized) sets *)

module SetTools(ASet: Set.S) =
struct
let find_duplicates l =
let rec aux l seen acc =
match l with
| [] -> acc
| h :: q ->
if ASet.mem h seen then
aux q seen (h :: acc)
else
aux q (ASet.add h seen) acc in
aux l (ASet.empty) []
end

module StringSet = Set.Make(String)

module StringSetTools = SetTools(StringSet)

StringSetTools.find_duplicates ["andrew"; "bob"; "chris"; "bob"];;

Fetch an element of a list by index

Given the list [One, Two, Three, Four, Five], fetch the third element ('Three')
ocaml
let third = List.nth [ "One"; "Two"; "Three"; "Four"; "Five" ] 3;;

Fetch the last element of a list

Given the list [Red, Green, Blue], access the last element ('Blue')
ocaml
let list = [ "Red"; "Green"; "Blue" ] in
let last = List.nth list ( (List.length list) - 1 );;
let list = [ "Red"; "Green"; "Blue" ] in
let last = List.hd (List.rev list);;
let list_last l =
let rec aux h q =
match q with
| [] -> h
| h :: q -> aux h q in
match l with
| [] -> invalid_arg "list_last"
| h :: q -> aux h q
;;
list_last ["Red"; "Green"; "Blue"]

Find the common items in two lists

Given two lists, find the common items. E.g. given beans = ['broad', 'mung', 'black', 'red', 'white'] and colors = ['black', 'red', 'blue', 'green'], what are the bean varieties that are also color names?
ocaml
let beans = ["broad"; "mung"; "black"; "red"; "white"]

let colors = ["black"; "red"; "blue"; "green"]

let f common c = if List.mem c beans then c::common else common

let common = List.fold_left f [] colors;;

(* common will contain a list with the common elements *)
(* using standard (functorized) sets *)

module SetTools(ASet: Set.S) =
struct
let of_list l =
List.fold_left (fun acc e -> ASet.add e acc) ASet.empty l

let find_common l1 l2 =
ASet.elements (ASet.inter (of_list l1) (of_list l2))
end

module StringSet = Set.Make(String)

module StringSetTools = SetTools(StringSet)
;;
let beans = ["broad"; "mung"; "black"; "red"; "white"] in
let colors = ["black"; "red"; "blue"; "green"] in
StringSetTools.find_common beans colors;;

Display the unique items in a list

Display the unique items in a list, e.g. given ages = [18, 16, 17, 18, 16, 19, 14, 17, 19, 18], display the unique elements, i.e. with duplicates removed.
ocaml
let ages = [18; 16; 17; 18; 16; 19; 14; 17; 19; 18]

let f res e = if List.mem e res then res else e::res

let unique = List.fold_left f [] ages;;
(* using standard (functorized) sets *)

module SetTools(ASet: Set.S) =
struct
let of_list l =
List.fold_left (fun acc e -> ASet.add e acc) ASet.empty l

let unique l =
ASet.elements (of_list l)
end

module Integer =
struct
type t = int
let compare (x:t) y = Pervasives.compare x y
end

module IntegerSet = Set.Make(Integer)
module IntegerSetTools = SetTools(IntegerSet)
;;
IntegerSetTools.unique [18; 16; 17; 18; 16; 19; 14; 17; 19; 18];;
let removeDuplicate list =
let rec aux acc = function
| [] -> acc
| h :: t -> if (List.mem h t) then aux acc t else aux (h::acc) t
in
List.rev (aux [] list);;

Remove an element from a list by index

Given the list [Apple, Banana, Carrot], remove the first element to produce the list [Banana, Carrot]
ocaml
let delete_at i al =
if i < 0 || i >= List.length al then
invalid_arg "delete_at"
else
let rec del i l =
match l with
| [] -> []
| h::t when i = 0 -> t
| h::t -> h :: del (i-1) t
in
del i al
;;
let rem_first l =
match l with
| [] -> []
| h::t -> t
;;
List.tl ["Apple"; "Banana"; "Carrot"]

Remove the last element of a list

ocaml
let remove_last list =
match (List.rev list) with
| h::t -> List.rev t
| [] -> []
let remove_last lst =
List.rev (List.tl (List.rev lst))
let list_remove_last l =
let rec aux h q acc =
match q with
| [] -> List.rev acc
| h2 :: q -> aux h2 q (h :: acc) in
match l with
| [] -> invalid_arg "list_remove_last"
| h :: q -> aux h q []

Rotate a list

Given a list ["apple", "orange", "grapes", "bananas"], rotate it by removing the first item and placing it on the end to yield ["orange", "grapes", "bananas", "apple"]
ocaml
let rotate list =
match list with
| head::tail -> tail@[head]
| [] -> []

Gather together corresponding elements from multiple lists

Given several lists, gather together the first element from every list, the second element from every list, and so on for all corresponding index values in the lists. E.g. for these three lists, first = ['Bruce', 'Tommy Lee', 'Bruce'], last = ['Willis', 'Jones', 'Lee'], years = [1955, 1946, 1940] the result should produce 3 actors. The middle actor should be Tommy Lee Jones.
ocaml
let rec combine3 f l y =
match f, l, y with
| [], [], [] -> []
| fh :: fq, lh :: lq, yh :: yq ->
(fh, lh, yh) :: combine3 fq lq yq
| _ -> invalid_arg "combine3"
;;
let first = ["Bruce"; "Tommy Lee"; "Bruce"] in
let last = ["Willis"; "Jones"; "Lee"] in
let years = [1955; 1946; 1940] in
combine3 first last years

List Combinations

Given two source lists (or sets), generate a list (or set) of all the pairs derived by combining elements from the individual lists (sets). E.g. given suites = ['H', 'D', 'C', 'S'] and faces = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'], generate the deck of 52 cards, confirm the deck size and check it contains an expected card, say 'Ace of Hearts'.
ocaml
let suites = ["H"; "D"; "C"; "S"]
let faces = ["2";"3";"4";"5";"6";"7";"8";"9";"10";"J";"Q";"K";"A"]

let desk =
List.fold_left (fun acc y ->
List.fold_left (fun acc2 x ->
(x, y)::acc2
) acc faces
) [] suites

let () =
assert (List.length desk = 52);
if List.mem ("A", "H") desk
then print_endline "Ace of Hearts found!"
else print_endline "Ace of Hearts not found :("

Perform an operation on every item of a list

Perform an operation on every item of a list, e.g.
for the list ["ox", "cat", "deer", "whale"] calculate
the list of sizes of the strings, e.g. [2, 3, 4, 5]
ocaml
List.map String.length ["ox"; "cat"; "deer"; "whale"];;

Split a list of things into numbers and non-numbers

Given a list that might contain e.g. a string, an integer, a float and a date,
split the list into numbers and non-numbers.
ocaml
(* OCaml is a strongly statically typed language so it is not possible to mix
items of different types in a single list.
So here we use a list of strings, some of these strings represent a number *)

let is_a_number v =
try ignore(float_of_string v); true
with _ -> false

let numbers, others =
List.partition is_a_number ["Joe"; "3.14"; "8"; "hello"; "23/04/2009"]

(* ========================================================================== *)
(* If we really want to mix items of several types, we can declare a variant: *)

type item = Int of int | Float of float | String of string | Char of char

let is_a_number = function
| Float _ | Int _ -> true
| String _ | Char _ -> false

let numbers, others =
List.partition is_a_number [String "Joe"; Float 3.14; Int 8; Char 'Z']

Test if a condition holds for all items of a list

Given a list, test if a certain logical condition (i.e. predicate) holds for all items of the list.
ocaml
(* from the interactive loop *)
# List.for_all (fun x -> x > 1) [2; 3; 4] ;;
- : bool = true

Test if a condition holds for any items of a list

Given a list, test if a certain logical condition (i.e. predicate) holds for any items of the list.
ocaml
(* from the interactive loop: *)
# List.exists (fun x -> x > 3) [2; 3; 4] ;;
- : bool = true