我试图创建一张遍历文档中所有ngrams的地图,并计算它们出现的频率。 Ngrams是句子中n个连续单词的集合(因此在最后一句中,(Ngrams,are)是2-gram,(are,sets)是下一个2-gram,依此类推)。我已经有了从文件创建文档并将其解析为句子的代码。我还有一个函数来计算句子中的ngrams,ngramsInSentence,它返回Seq [Ngram]。
我在语法上遇到了如何创建我的计数贴图的问题。我在for循环中迭代文档中的所有ngrams,但不知道如何将nmap映射到它们出现频率的计数。我对Scala相当陌生,语法正在躲避我,尽管我在概念上清楚地表达了我需要的东西!
def getNGramCounts(document: Document, n: Int): Counts = {
for (sentence <- document.sentences; ngram <- nGramsInSentence(sentence,n))
//I need code here to map ngram -> count how many times ngram appears in document
}
上面的计数类型以及Ngram定义为:
type Counts = Map[NGram, Double]
type NGram = Seq[String]
有没有人知道将n循环从for循环映射到它们发生频率的计数的语法?如果您想了解有关此问题的更多详细信息,请与我们联系。
答案 0 :(得分:2)
如果我正确地解释你的代码,这是一个相当常见的任务。
def getNGramCounts(document: Document, n: Int): Counts = {
val allNGrams: Seq[NGram] = for {
sentence <- document.sentences
ngram <- nGramsInSentence(sentence, n)
} yield ngram
allNgrams.groupBy(identity).mapValues(_.size.toDouble)
}
allNGrams
变量收集文档中出现的所有NGrams的列表
如果文档很大并且您无法将整个序列保存在内存中,则最终应转向Stream
。
以下groupBy
创建了一个Map[NGram, List[NGram]]
,它按照标识对您的值进行分组(方法的参数定义了“聚合标识”的标准),并将相应的值分组到列表中。
然后,您只需将值(List[NGram]
)映射到其size
,即可获得每个NGram
的重复值。
我理所当然地认为:
NGram
正确实现了equals
+ hashcode
document.sentences
返回Seq[...]
。如果不是,您应该期望allNGrams
属于相应的集合类型。更新
我错误地认为groupBy(_)
会快捷输入值。请改用identity
功能。
我将计数转换为Double
答案 1 :(得分:0)
感谢帮助 - 我现在使用上面的建议获得了正确的代码。以下内容返回所需的结果:
def getNGramCounts(document: Document, n: Int): Counts = {
val allNGrams: Seq[NGram] = (for(sentence <- document.sentences;
ngram <- ngramsInSentence(sentence,n))
yield ngram)
allNGrams.groupBy(l => l).map(t => (t._1, t._2.length.toDouble))
}