Reputation: 2416
What is the fastest way to get the position of an element in a list of element in OCaml? I know how to get the "nth" position of an element in a list but I would like to know how to get the position of this element if I already know the value.
Upvotes: 2
Views: 3071
Reputation: 36581
If the elements in a list are all unique, you may wish to convert to a map, where the elements are keys and the indices are values. The creation of the map is O(n), but subsequently, lookups of indices are O(log n).
E.g.
module IntMap = Map.Make (Int)
let lst = [34; 56; 17; 2; 0; 99]
let indexed_lst = List.mapi (fun x i -> (i, x)) lst
let map =
List.fold_left
(fun m (k, v) -> IntMap.add k v m)
IntMap.empty
indexed_lst
let idx_of_2 = IntMap.find 2 map
Now idx_of_2
is 3
.
This is more expensive than a linear search for very low numbers of lookups, but increasingly less expensive as the number of lookups increases.
If numbers in the list are not unique, we could generate a map with lists of indices.
let lst = [34; 56; 17; 2; 0; 99; 2; 34]
let indexed_lst = List.mapi (fun x i -> (i, x)) lst
let map =
List.fold_left
(fun m (k, v) ->
IntMap.update
k
(function
| None -> Some [v]
| Some vs -> Some (v::vs))
m)
IntMap.empty
indexed_lst
|> IntMap.map List.rev
let idx_of_2 = IntMap.find 2 map
In this situation, idx_of_2
would now be [3; 6]
.
Upvotes: 0
Reputation: 2004
let rec findi_rec base p l =
match l with
[] -> raise Not_found
| h::_ when p h -> base
| _::t -> findi_rec (base+1) p t;;
let findi p l = findi_rec 0 p l;;
As:
# findi (fun x -> x=4) [1;9;3;2;1;4;5;7];;
- : int = 5
Upvotes: 0
Reputation: 25812
I believe the fastest is way is the most usual way:
The time complexity will be O(N)
let index_of e l =
let rec index_rec i = function
| [] -> raise Not_found
| hd::tl -> if hd = e then i else index_rec (i+1) tl
in
index_rec 0 l
Upvotes: 11