计算列表中元素的出现次数

mol*_*erx 4 f#

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

我已经提出了下面的内容,但是temp的返回类型存在问题:"类型'int'与类型''列表'不匹配".但是,这三种返回类型对我来说是一致的.我做错了什么?如果我所做的不是好F#而且应该以完全不同的方式完成,请也让我知道.

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
    | [] -> []
Run Code Online (Sandbox Code Playgroud)

Bri*_*ian 26

编辑:哎呀,这不回答你的问题,因为你说"连续".但我会留在这里,因为搜索问题标题的人可能会发现它很有用.

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)]
Run Code Online (Sandbox Code Playgroud)

  • 这里的“id”是什么? (2认同)

nyi*_*ann 9

这个如何?

lst |> Seq.groupBy (fun x -> x) |> Seq.map (fun (a,b) -> (a, Seq.length(b)))
Run Code Online (Sandbox Code Playgroud)

  • `(fun x - > x)`可以拼写为`id` (6认同)

kvb*_*kvb 4

在这一行中:

| x::xs when x=collecting -> temp xs collecting counted+1
Run Code Online (Sandbox Code Playgroud)

编译器将你的代码解释为

| x::xs when x=collecting -> (temp xs collecting counted)+1
Run Code Online (Sandbox Code Playgroud)

但你想要的是

| x::xs when x=collecting -> temp xs collecting (counted+1)
Run Code Online (Sandbox Code Playgroud)

然而,即使进行了这一更改,您的算法的一个问题是该temp函数不是尾递归的,这意味着在长列表上调用时可能会导致堆栈溢出(例如countoccurences [1..10000]在我的机器上失败)。如果这对您很重要,那么您应该将temp辅助函数重写为尾递归。最简单的方法是添加一个累积列表参数,然后反转列表。

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
    | [] -> []
Run Code Online (Sandbox Code Playgroud)