I have two lists, ["0","1"] and ["0","1","0"], and I want to get a list, [(0,2),(1,1)], - which associates to each element of the first list the number of its occurrences in the second list. I tried this:
let partialSolution =
List.map(
fun x ->
let subsubList = List.for_all (fun y -> (String.compare x y)=0) ) ("0"::("1"::("0"::[]))) in
(x, List.length ( List.filter ( fun z -> z = true) subsubList ) )
) ;;
, but it's not good: it gives me these errors:
# let partialSolution =
# List.map(
# fun x ->
# let subsubList = List.for_all (fun y -> (String.compare x y)=0) )
File "", line 4, characters 73-74:
Error: Syntax error: operator expected.
# ("0"::("1"::("0"::[]))) in
File "", line 4, characters 99-101:
Error: Syntax error
# (x, List.length ( List.filter ( fun z -> z = true) subsubList ) )
# )
File "", line 6, characters 0-1:
Error: Syntax error
# ;;
File "", line 6, characters 2-4:
Error: Syntax error
I would like to understand how I can fix this - I am a total newbie to OCaml.
You're a bit overzealous with the parentheses. The syntax error is caused by an extra closing parentheses after (fun y -> ...)
.
But you'll still have a type error, since List.for_all
returns a bool
, true
if all items satisfy the predicate and false
otherwise. It seems you want to use List.map
here instead.
You also don't need to surround every use of ::
with parentheses. ("0"::"1"::"0"::[])
is fine, but you can also just reduce this to a simple list literal: ["0"; "1"; "0"]
. Additionally, z = true
is equivalent to z
, though perhaps slightly less readable.
This compiles. I haven't checked whether it actually does what you want though:
let partialSolution =
List.map
begin fun x ->
let subsubList =
List.map
(fun y -> String.compare x y = 0)
["0"; "1"; "0"]
in
(x, List.length (List.filter (fun z -> z) subsubList))
end
Also, if you're using 4.03 or higher you can use String.equal
, and if you're using 4.08 you can use Fun.id
instead of the ad hoc lambda functions:
let partialSolution =
List.map
begin fun x ->
let subsubList =
List.map (String.equal x) ["0"; "1"; "0"]
in
(x, List.length (List.filter Fun.id subsubList))
end
Or instead of dealing with an intermediate bool list
, you could use List.fold_left
to do a count directly:
let partialSolution =
List.map
begin fun x ->
let count =
List.fold_left
(fun count y ->
if String.compare x y = 0 then
count + 1
else
count)
0 ["0"; "1"; "0"]
in
(x, count)
end