Scala:列表元素的groupBy(标识)

sgz*_*zmd 9 scala

我开发了一个应用程序,它在(标记化的)文本中构建单词对,并产生每对发生的次数(即使同一对词出现多次,也可以,因为它将在算法的后期得到均衡).

我用的时候

elements groupBy()
Run Code Online (Sandbox Code Playgroud)

我想按元素的内容进行分组,所以我写了以下内容:

def self(x: (String, String)) = x

/**
 * Maps a collection of words to a map where key is a pair of words and the 
 *  value is number of
 * times this pair
 * occurs in the passed array
 */
def producePairs(words: Array[String]): Map[(String,String), Double] = {
  var table = List[(String, String)]()
  words.foreach(w1 =>
    words.foreach(w2 =>
      table = table ::: List((w1, w2))))


  val grouppedPairs = table.groupBy(self)
  val size = int2double(grouppedPairs.size)
  return grouppedPairs.mapValues(_.length / size)
}
Run Code Online (Sandbox Code Playgroud)

现在,我完全意识到这个自我()技巧是一个肮脏的黑客.所以我想到了一点:

grouppedPairs = table groupBy (x => x)
Run Code Online (Sandbox Code Playgroud)

这样就产生了我想要的东西.但是,我仍然觉得我明显错过了一些东西,应该有更简单的方法.亲爱的,有什么想法吗?

另外,如果你帮我改进了对提取部分,它也会有很大帮助 - 它看起来非常迫切,C++ - 现在就是这样.提前谢谢了!

Lan*_*dei 13

我建议这个:

def producePairs(words: Array[String]): Map[(String,String), Double] = {
    val table = for(w1 <- words; w2 <- words) yield (w1,w2)
    val grouppedPairs = table.groupBy(identity)
    val size = grouppedPairs.size.toDouble
    grouppedPairs.mapValues(_.length / size)
}
Run Code Online (Sandbox Code Playgroud)

for comprehension更容易阅读,并且已经有一个预先设定的功能identity,是你的一般化版本self.


0__*_*0__ 2

您正在通过迭代单词两次来创建所有单词对的所有单词对的列表,我猜您只需要相邻的对。最简单的方法是使用滑动视图。

def producePairs(words: Array[String]): Map[(String, String), Int] = {
  val pairs   = words.sliding(2, 1).map(arr => arr(0) -> arr(1)).toList
  val grouped = pairs.groupBy(t => t)
  grouped.mapValues(_.size)
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是通过求和来折叠配对列表。但不确定这是否更有效:

def producePairs(words: Array[String]): Map[(String, String), Int] = {
  val pairs = words.sliding(2, 1).map(arr => arr(0) -> arr(1))
  pairs.foldLeft(Map.empty[(String, String), Int]) { (m, p) =>
     m + (p -> (m.getOrElse(p, 0) + 1))
  }
}
Run Code Online (Sandbox Code Playgroud)

我看到你返回一个相对数字(双精度)。为简单起见,我刚刚计算了出现次数,因此您需要进行最后的除法。我认为你想除以总对的数量 (words.size - 1) 而不是除以唯一对的数量 (grouped.size)...,因此相对频率总和为 1.0