Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 统计列表中元素的出现次数_F# - Fatal编程技术网

F# 统计列表中元素的出现次数

F# 统计列表中元素的出现次数,f#,F#,我有一个整数列表,任何多次出现的整数都会连续出现。我想将其转换为元组列表,其中包含每个对象及其计数 我已经提出了以下问题,但是temp的返回类型有一个问题:“类型'int'与类型'a list'不匹配。”。然而,在我看来,这三种回报类型是一致的。我做错了什么?如果我做的不好,应该以完全不同的方式来做,也请让我知道 let countoccurences list = match list with | x::xs -> let rec temp list collectin

我有一个整数列表,任何多次出现的整数都会连续出现。我想将其转换为元组列表,其中包含每个对象及其计数

我已经提出了以下问题,但是temp的返回类型有一个问题:“类型'int'与类型'a list'不匹配。”。然而,在我看来,这三种回报类型是一致的。我做错了什么?如果我做的不好,应该以完全不同的方式来做,也请让我知道

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
是什么?