[英]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
。 一起研究Reed和torbonde的答案的相关部分:
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) a
与g (fa)
相同), ~-
是一元负运算符。 注意这里的运算符本质上是函数,但是当使用(并声明)它们作为函数时,必须将它们包装在括号中。 也就是说, -3
与(~-) 3
,在最后一种情况下,我们将运算符用作函数。
总的来说,倒数第二行所做的是按该对中第二个条目的负值(出现的次数)对序列进行排序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.