Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OCaml map a string to a list of strings

Tags:

python

ocaml

I'm trying to create a dictionary in OCaml that maps a string to a list of strings. I've referenced this tutorial for a basic string to string map, but I need some help making a list.

Here is what I want to do in Python:

>>> food = {}
>>> food["fruit"] = ("blueberry", "strawberry", "kiwi")
>>> food["veggie"] = ("broccoli", "kale")
>>> for k in food:
...     for v in food[k]:
...         print k, "-->",v
...
fruit --> blueberry
fruit --> strawberry
fruit --> kiwi
veggie --> broccoli
veggie --> kale

Thanks in advance

like image 956
DC00 Avatar asked Jan 28 '16 19:01

DC00


2 Answers

You can just use lists,

let food = [
  "fruit",  ["blueberry"; "strawberry"; "kiwi"];
  "veggie", ["broccoli"; "kale"]
]

and use List.assoc to access it:

List.assoc "fruit" food

will evaluate to

- : string list = ["blueberry"; "strawberry"; "kiwi"]

If you need real maps with logarithmic search, then you can use Map module. In standard library it provides a functor Make that will create a map for a user provided data, e.g.,

module Strings = Map.Make(String)

will create a module Strings that is a map from string type to anything else. You can easily use lists as your value type:

let map = Strings.empty 
Strings.add "fruit" ["blueberry"; "strawberry"; "kiwi"] map

This will, of course, create a persistent map. If you need a mutable map, like in python, then you need a Hashtbl module.

Here is an example with Hashtbl:

let food = Hashtbl.create 16
Hashtbl.add food "fruit" ["blueberry"; "strawberry"; "kiwi"]
Hashtbl.add food "veggie" ["broccoli"; "kale"]
Hashtbl.find food "veggie"

Will evaluate to

- : string list = ["broccoli"; "kale"]
like image 71
ivg Avatar answered Oct 12 '22 02:10

ivg


Arrays and lists are not the same in OCaml. I'll assume you want to use lists (as in your title) and not arrays (as in the body of your question).

Here are some slightly modified lines from the tutorial:

# module myStrings = Map.Make(String);;
module MyStrings :
sig
 . . .
end
# let m0 = MyStrings.empty;;
val m0 : 'a MyStrings.t = <abstr>
# let m1 = MyStrings.add "abc" ["def"; "ghi"] m0;;
val m1 : string list MyStrings.t = <abstr>
# MyStrings.iter
    (fun s ss -> Printf.printf "%s --> %s\n" s (String.concat " " ss))
    m1;;
abc --> def ghi
- : unit = ()
like image 21
Jeffrey Scofield Avatar answered Oct 12 '22 00:10

Jeffrey Scofield