Functional programming 在OCaml中按对的键筛选对的列表
我有一个模拟字典的对的列表,比如Functional programming 在OCaml中按对的键筛选对的列表,functional-programming,ocaml,Functional Programming,Ocaml,我有一个模拟字典的对的列表,比如[(“key1”,32);(“key2”,54);…],我需要一个函数,可以过滤列表并返回一个新列表,删除具有重复键的对 例如:像[(“key”,32);(“key”,78);(“anotherKey”,12)]这样的列表必须过滤为[(“key”,32);(“anotherKey”,12)] 我使用哈希表实现了这一点,但我更喜欢使用列表的解决方案。在下面的代码中,我找不到用列表替换哈希表的方法,因为在else分支中,我不知道如何正确更新seen列表 let get
[(“key1”,32);(“key2”,54);…]
,我需要一个函数,可以过滤列表并返回一个新列表,删除具有重复键的对
例如:像[(“key”,32);(“key”,78);(“anotherKey”,12)]
这样的列表必须过滤为[(“key”,32);(“anotherKey”,12)]
我使用哈希表实现了这一点,但我更喜欢使用列表的解决方案。在下面的代码中,我找不到用列表替换哈希表的方法,因为在else
分支中,我不知道如何正确更新seen
列表
let getKey (k,v) = k;;
(* Hashtable *)
let filter (list : (string * int list) : (string * int) list =
let seen = Hashtbl.create (List.length list) in
List.filter ( fun pair -> let exists = not (Hashtbl.mem seen (getKey pair)) in
Hashtbl.replace seen (getKey pair) (); exists) list
;;
(* List *)
let filter (list : (string * int) list) : (string * int) list =
let seen = [] in
List.filter ( fun pair -> let exists = List.mem (getKey pair) seen in
if exists then failwith("duplicate")
else (* what to do here? *) ; true) list
;;
我不太清楚问题出在哪里。对我来说,解决方案可以非常清楚地表达出来:
let rec is_member key = function
| [] -> false
| (k, _)::tail ->
if k = key then true
else is_member key tail
;;
let dedup list =
let rec aux acc = function
| [] -> List.rev acc
| ((k, v) as hd)::tl ->
if is_member k acc then aux acc tl
else aux (hd::acc) tl
in aux [] list
;;
utop # dedup [("key",32);("key",78);("anotherKey",12)];;
- : (string * int) list = [("key", 32); ("anotherKey", 12)]
关于标准库(尤其是列表),使用List.filter
,您无法实现目标,因为此函数不累加结果,而只是逐个迭代列表元素。如果需要累积结果,则应使用smth。像向左折叠
,例如:
let dedup_list list =
List.fold_left (fun acc ((k, v) as el) -> if is_member k acc then acc else el::acc) [] list
|> List.rev
;;
utop # dedup_list [("key",32);("key",78);("anotherKey",12)];;
- : (string * int) list = [("key", 32); ("anotherKey", 12)]
我不太清楚问题出在哪里。对我来说,解决方案可以非常清楚地表达出来:
let rec is_member key = function
| [] -> false
| (k, _)::tail ->
if k = key then true
else is_member key tail
;;
let dedup list =
let rec aux acc = function
| [] -> List.rev acc
| ((k, v) as hd)::tl ->
if is_member k acc then aux acc tl
else aux (hd::acc) tl
in aux [] list
;;
utop # dedup [("key",32);("key",78);("anotherKey",12)];;
- : (string * int) list = [("key", 32); ("anotherKey", 12)]
关于标准库(尤其是列表),使用List.filter
,您无法实现目标,因为此函数不累加结果,而只是逐个迭代列表元素。如果需要累积结果,则应使用smth。像向左折叠
,例如:
let dedup_list list =
List.fold_left (fun acc ((k, v) as el) -> if is_member k acc then acc else el::acc) [] list
|> List.rev
;;
utop # dedup_list [("key",32);("key",78);("anotherKey",12)];;
- : (string * int) list = [("key", 32); ("anotherKey", 12)]
您需要使筛选器递归并将更新的seen传递给下一个调用。您需要使筛选器递归并将更新的seen传递给下一个调用。