我有一个列表:
let lst = ["cat"; "dog"; "cow"; "dog"; "cat"; "horse"; "dog"];;
我想计算相同元素的数量,并将输出放在元组列表中(元素,计数),如:
[("cat", 2); ("dog", 3); ("cow", 1); ("horse", 1)]
我尝试使用List.fold_left
,但发现折叠功能很复杂。有什么建议吗?
答案 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 []