计算OCaml中列表中重复项的数量

时间:2014-03-03 08:19:51

标签: ocaml

我有一个列表:

let lst = ["cat"; "dog"; "cow"; "dog"; "cat"; "horse"; "dog"];;

我想计算相同元素的数量,并将输出放在元组列表中(元素,计数),如:

[("cat", 2); ("dog", 3); ("cow", 1); ("horse", 1)]

我尝试使用List.fold_left,但发现折叠功能很复杂。有什么建议吗?

3 个答案:

答案 0 :(得分:2)

如果你不关心表现,那就可以这样:

let count_dup l =
  let scan_count x l = List.fold_left (fun (c,acc) y -> if x = y then c+1,acc else c,y::acc) (1,[]) l in
  let rec count acc = function
    | [] -> List.rev acc
    | hd::tl -> let c,r = scan_count hd tl in count ((hd,c)::acc) r
  in 
  count [] l

如果您关心性能,但不关心订单,那么最好先对列表进行排序,然后再扫描一次。

let count_dup' l = 
  let sl = List.sort compare l in
  match sl with
    | [] -> []
    | hd::tl -> 
      let acc,x,c = List.fold_left (fun (acc,x,c) y -> if y = x then acc,x,c+1 else (x,c)::acc, y,1) ([],hd,1) tl in
      (x,c)::acc

答案 1 :(得分:1)

let count l =
    let hash = Hashtbl.create 10 in
    List.iter (fun key -> if Hashtbl.mem hash key then Hashtbl.replace hash key ((Hashtbl.find hash key) + 1) else Hashtbl.add hash key 1) l;
    Hashtbl.fold (fun k v ls -> (k, v) :: ls) hash []

答案 2 :(得分:0)

保持订单和效果的方法:

    let count lst = 
      let sorted = List.sort (compare) lst in
      List.fold_right (fun ele acc -> match acc with 
                                      | [] -> [(ele, 1)]
                                      | (ele', c)::t -> 
                                           if ele = ele' 
                                           then (ele, c+1)::t
                                           else (ele,1)::(ele',c)::t) sorted []