Loading ...
Sorry, an error occurred while loading the content.

13944Re: "ocaml_beginners"::[] how to simplify "nesting" of lists when using fold

Expand Messages
  • Toby Kelsey
    Aug 23, 2013
    • 0 Attachment
      Your Hashtbl value type is (1) a reference to (2) a (singeton) list of (3) your
      real data-type (list of string). Both the reference and extra list seem to be
      unnecessary levels of indirection. Is there some reason you don't just use the
      basic data type?

      The other main issues I see are that you create multiple shadowed variables
      called 'more' which you don't use meaningfully, and you uniquify the keys which
      is unnecessary if you consistently avoid adding duplicates or always use
      Hashtbl.replace instead of add.

      Here is what it looks like simplified and compileable (superfluous list version
      in comments):

      type data_t = string list
      (*type data_t = string list list*)

      let print_val d =
      List.iter (fun s -> print_string (" "^s)) d;
      print_newline()
      ;;

      let print_key x = print_int x; print_newline();;

      exception Invalid_entry of string;;

      let add tbl key v =

      if Hashtbl.mem tbl key then raise (Invalid_entry "Item already in database")
      else
      Hashtbl.replace tbl key v
      (* Hashtbl.replace tbl key [v] *)
      ;;

      (* print keys already in database *)
      let keys tbl =

      Hashtbl.fold (fun key value ls -> key :: ls) tbl [];;

      (* now show inventory *)
      let values tbl =

      let vals = Hashtbl.fold (fun key value ls -> value :: ls) tbl [] in
      (* are duplicate values an error? if so this should raise an exception *)
      List.fold_left (fun ls x -> if List.mem x ls then ls else x :: ls) [] vals ;;

      (* example: *)

      let (db : (int, data_t) Hashtbl.t) = Hashtbl.create 10 ;;

      add db 10100321 ["10100321"; "transverse axle and bearing"; "third shelf; 2
      isle; upper lory"; "vendor part number 33001"; "y"; "199.99";] ;;
      add db 10100322 ["10100322"; "gear box"; "2nd shelf, 5th isle, upper lory";
      "vendor part number 45002"; "y"; "139.99"; ] ;;
      add db 10100416 ["10100416"; "spring release"; "1st shelf;2nd isle; lower case";
      "vendor part number 63102"; "y"; "19.89"; ] ;;

      print_endline "keys:";;
      List.iter print_key (keys db);;

      print_endline "values:";;
      List.iter print_val (values db);;
      (*List.iter (fun l -> print_val (List.hd l)) (values db);;*)


      On 23/08/13 09:20, Jean Saint-Remy wrote:
      > Hi,
      >
      > I am trying to reduce complexity when "collating" lists of lists. The auto parts database program seems to work for the time being, but the share holders are not amused when we try to run inventory reports.
      >
      > let (db : (int, 'a list ref) Hashtbl.t) = Hashtbl.create 10 ;;
      > exception Invalid_entry of string;;
      > let add tbl key data =
      >
      > let more =
      >
      > if (Hashtbl.mem tbl key) then raise (Invalid entry "Item already in database")
      > else
      > let more = ref [] in
      > Hashtbl.add tbl key more;
      > more in
      > more := data :: [] ;;
      > add db 10100321 ["10100321"; "transverse axle and bearing"; "third shelf; 2 isle; upper lory"; "vendor part number 33001"; "y"; "199.99";] ;;
      > add db 10100322 ["10100322"; "gear box"; "2nd shelf, 5th isle, upper lory"; "vendor part number 45002"; "y"; "139.99"; ] ;;
      > add db 10100416 ["10100416"; "spring release"; "1st shelf;2nd isle; lower case"; "vendor part number 63102"; "y"; "19.89"; ] ;;
      >
      > (* print keys already in database *)
      > let keys tbl =
      >
      > let key = Hashtbl.fold (fun key value ls -> key :: ls) tbl [] in
      > List.fold_left (fun ls x -> if List.mem x ls then ls else x :: ls) [] key ;;
      >
      > (* now show inventory *)
      > let values tbl =
      > let value = Hashtbl.fold (fun key value ls -> value :: ls) tbl [] in
      >
      > List.fold_left (fun ls x -> if List.mem x ls then ls else x :: ls) [] value ;;
      > # keys db ;;
      > -: int list = [10100416; 10100322; 10100321]
      >
      >
      > # values db ;;
      > - : string list list ref list =
      > [{contents =
      > [["10100321"; "transverse axle and bearing"; "third shelf; 2 isle; upper lory"; "vendor part number 33001"; "y"; "199.99";]]};
      > {contents =
      > [["10100322"; "gear box"; "2nd shelf, 5th isle, upper lory"; "vendor part number 45002"; "y"; "139.99"; ]]};
      > {contents =
      > [["10100416"; "spring release"; "1st shelf;2nd isle; lower case"; "vendor part number 63102"; "y"; "19.89"; ]]}]
      >
      >
      > It is fine for generating keys from the hash table, but clearly above we have list inside of a list of a list, which seems to increase the program complexity. We wanted to cons a list of lists [ [list1]; [list2]; [list3] ], but things did not go so well.
      >
      >
      > How can we traverse the hash and produce a simple list? Do we need to call "List.hd" on the result to sort of decompose the lists?
      >
      > With kind regards,
      >
      > Jean
      >
      >
      > [Non-text portions of this message have been removed]
      >
      >
    • Show all 2 messages in this topic