繁体   English   中英

F#:生成字数摘要

[英]F#: Generating a word count summary

我是编程新手,F#是我的第一门.NET语言。

我想阅读文本文件的内容,计算每个单词的出现次数,然后返回10个最常见的单词以及每个单词出现的次数。

我的问题是:在F#中鼓励使用字典吗? 如果我想使用字典,该如何编写代码? (我已经浏览了MSDN上的Dictionary类,但是我仍然对如何将值更新为键感到困惑。)我是否总是必须在函数式编程中使用Map?

我的问题是:在F#中鼓励使用字典吗?

从F#开始,使用Dictionary是可以的,尽管它确实使用可变性,所以它并不常见。

如果我想使用字典,该如何编写代码?

如果您读取文件,并使用逗号分隔值的字符串,则可以使用类似于以下内容的语法进行解析:

// Just an example of input - this would come from your file...
let strings = "one, two, one, three, four, one, two, four, five"
let words = 
    strings.Split([|','|]) 
    |> Array.map (fun s -> s.Trim())

let dict = Dictionary<_,_>()
words
|> Array.iter (fun w -> 
    match dict.TryGetValue w with
    | true, v -> dict.[w] <- v + 1
    | false, _ -> dict.[w] <- 1)

// Creates a sequence of tuples, with (word,count) in order
let topTen =
    dict
    |> Seq.sortBy (fun kvp -> -kvp.Value)
    |> Seq.truncate 10
    |> Seq.map (fun kvp -> kvp.Key, kvp.Value)

尽管其他答案没有错,但我想指出的是,已经有一个专门的功能来获取序列中唯一键的数量: Seq.countBy 一起研究Reedtorbonde的答案的相关部分:

let countWordsTopTen (s : string) =
    s.Split([|','|]) 
    |> Seq.countBy (fun s -> s.Trim())
    |> Seq.sortBy (snd >> (~-))
    |> Seq.truncate 10

"one, two, one, three, four, one, two, four, five"
|> countWordsTopTen
|> printfn "%A" // seq [("one", 3); ("two", 2); ("four", 2); ("three", 1); ...]

我要说的一个明显选择是使用Seq模块,它实际上是F#中的主要力量之一。 正如里德所说,使用字典并不常见,因为它是可变的。 另一方面,序列是不可变的。 如何使用序列执行此操作的示例是

let strings = "one, two, one, three, four, one, two, four, five"
let words =
  strings.Split([|','|]) 
  |> Array.map (fun s -> s.Trim())

let topTen =
  words
  |> Seq.groupBy id
  |> Seq.map (fun (w, ws) -> (w, Seq.length ws))
  |> Seq.sortBy (snd >> (~-))
  |> Seq.truncate 10

我认为代码本身就说明了很多,尽管也许倒数第二行需要简短说明: snd -function给出一对中的第二个条目(即snd (a,b)b ), >>是函数组成运算符(即(f >> g) ag (fa)相同), ~-是一元负运算符。 注意这里的运算符本质上是函数,但是当使用(并声明)它们作为函数时,必须将它们包装在括号中。 也就是说, -3(~-) 3 ,在最后一种情况下,我们将运算符用作函数。

总的来说,倒数第二行所做的是按该对中第二个条目的负值(出现的次数)对序列进行排序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM