F# 统计列表中元素的出现次数
我有一个整数列表,任何多次出现的整数都会连续出现。我想将其转换为元组列表,其中包含每个对象及其计数 我已经提出了以下问题,但是temp的返回类型有一个问题:“类型'int'与类型'a list'不匹配。”。然而,在我看来,这三种回报类型是一致的。我做错了什么?如果我做的不好,应该以完全不同的方式来做,也请让我知道F# 统计列表中元素的出现次数,f#,F#,我有一个整数列表,任何多次出现的整数都会连续出现。我想将其转换为元组列表,其中包含每个对象及其计数 我已经提出了以下问题,但是temp的返回类型有一个问题:“类型'int'与类型'a list'不匹配。”。然而,在我看来,这三种回报类型是一致的。我做错了什么?如果我做的不好,应该以完全不同的方式来做,也请让我知道 let countoccurences list = match list with | x::xs -> let rec temp list collectin
let countoccurences list =
match list with
| x::xs -> let rec temp list collecting counted =
match list with
| x::xs when x=collecting -> temp xs collecting counted+1
| x::xs -> (collecting,counted)::temp xs x 1
| [] -> (collecting,counted)::[]
temp xs x 1
| [] -> []
我可能会为此使用可变的解决方案。可能是这样的:
let countOccurrences l =
let counts = System.Collections.Generic.Dictionary()
l |> List.iter (fun x ->
match counts.TryGetValue(x) with
| true, i -> counts.[x] <- i + 1
| _ -> counts.Add(x, 1))
counts |> Seq.map (|KeyValue|)
let countl=
let counts=System.Collections.Generic.Dictionary()
l|>List.iter(乐趣x->
匹配计数。TryGetValue(x)与
|对,i->counts。[x]counts.Add(x,1))
计数|>Seq.map(|键值|)
编辑
我忘记了countBy(实现方式类似)。编辑:哎呀,这并不能回答你的问题,因为你说的是“连续的”。但我将把它留在这里,因为有人搜索问题标题可能会发现它很有用
Seq.countBy
执行此操作
let list = [1;2;3;4;5;6;1;2;3;1;1;2]
let results = list |> Seq.countBy id |> Seq.toList
printfn "%A" results
// [(1, 4); (2, 3); (3, 2); (4, 1); (5, 1); (6, 1)]
在这方面:
| x::xs when x=collecting -> temp xs collecting counted+1
编译器将您的代码解释为
| x::xs when x=collecting -> (temp xs collecting counted)+1
但你想要的是
| x::xs when x=collecting -> temp xs collecting (counted+1)
但是,即使进行了此更改,您的算法的一个问题是temp
函数不是尾部递归函数,这意味着在长列表上调用它时可能会导致堆栈溢出(例如,countoccurrences[1..10000]
在我的计算机上失败)。如果这对您很重要,那么您应该将temp
helper函数重写为尾部递归函数。最简单的方法是添加累积列表参数,然后反转列表
let countoccurences list =
match list with
| x::xs ->
let rec temp list collecting counted acc =
match list with
| x::xs when x = collecting -> temp xs collecting (counted+1) acc
| x::xs -> temp xs x 1 ((collecting, counted)::acc)
| [] -> (collecting, counted)::acc
temp xs x 1 []
|> List.rev
| [] -> []
这个怎么样
lst |> Seq.groupBy (fun x -> x) |> Seq.map (fun (a,b) -> (a, Seq.length(b)))
如果使用递归遍历列表,则始终可以使用fold
let countOccurrences = function
| [] -> []
| x::xs -> ([(x,1)],xs)
||> List.fold(fun ((y,c)::acc) x -> if x = y then (y,c+1)::acc else (x,1)::(y,c)::acc)
|> List.rev
(fun x->x)
可以拼写为id
不知道为什么这比@Brian的答案有更多的赞成票countBy
完全符合OP的要求。@Daniel投票是关于人的行为而不是正确性的。@gradbot-我认为有一个内置的解决方案值得向未来的访问者指出。TBH@Brian的解决方案可能更短更简单,但对我来说,这个解决方案更具可读性我喜欢这样。虽然我不喜欢元组结果。有没有办法让它只返回整数?假设我很幸运,我可以通过列表的索引值来识别结果。这里的id
是什么?