Scala - 减少功能

时间:2014-06-14 04:05:07

标签: scala mapreduce word-count

如何在Scala中使用reduce函数?有这样的内置功能吗? 我已经实现了一个程序来查找scala中的字数。

object count {
    def main(args: Array[String]) {
        val fruits = List("apple", "apple", "orange", "apple", "mango", "orange")
        val word = fruits.flatMap(_.split("\n"))
        val Map = word.map(word => (word,1)).groupBy(_._1)
        val reduce = Map.map(word => (word._1,word._2.foldLeft(0)((sum,c) => sum+ c._2)))
        println(reduce)     }} 

如何用reduce函数替换foldleft?

3 个答案:

答案 0 :(得分:14)

上面的整个示例应该像这样实现

fruits groupBy(word => word) mapValues(_.size)

或像这样替换折叠

val reduce = Map.map(word => (word._1,word._2.size))

但是如果你绝对肯定必须在相同的代码中使用reduce,那就是这样的

val reduce = Map.map(word => (word._1,word._2.map(_=>1).reduce(_+_)))

答案 1 :(得分:2)

您的示例可以更简单地完成,如下所示:

> fruits.groupBy(identity).mapValues(_.size) 
res176: Map[String, Int] = Map("mango" -> 1, "orange" -> 2, "apple" -> 3)

但是,如果要并行化并使用MapReduce模式,reduce在这里很有用。如果不进行并行化,则只需按顺序减少一个列表(1,1,1,1 ...)。比较:

> List(1,1,1,1,1,1,1).reduce{(a,b) => println(s"$a+$b=${a+b}"); a + b} 
1+1=2
2+1=3
3+1=4
4+1=5
5+1=6
6+1=7
res187: Int = 7

使用并行化版本(请注意par方法):

> List(1,1,1,1,1,1,1).par.reduce{(a,b) => println(s"$a+$b=${a+b}"); a + b} 
1+1=2
1+1=2
1+2=3
1+1=2
2+2=4
3+4=7
res188: Int = 7

您可以通过定义常用的reduceByKey函数来使用MapReduce模式,如下所示:

implicit class MapReduceTraversable[T, N](val traversable: Traversable[(T, N)]) {
  def reduceByKey(f: (N, N) => N) = traversable.par.groupBy(_._1).mapValues(_.map(_._2)).mapValues(_.reduce(f))
}

val fruits = List("apple", "apple", "orange", "apple", "mango", "orange", "apple", "apple", "apple", "apple") 

fruits.map(f => (f,1)).reduceByKey(_ + _)

res2: collection.parallel.ParMap[String, Int] = ParMap(orange -> 2, mango -> 1, apple -> 7)

你可以像以前一样调试它:

fruits.map(f => (f,1)).reduceByKey{(a,b) => println(s"$a+$b=${a+b}"); a + b} 

1+1=2
1+1=2
2+1=3
3+1=4
4+1=5
5+1=6
6+1=7
res9: Map[String, Int] = Map("mango" -> 1, "orange" -> 2, "apple" -> 7)

答案 2 :(得分:0)

不,没有内置功能,表现得像那样。您可以使用mapValues代替第二map来简化它,但没有类似的foldValues