情景设定:
从一组投票结果(语言,票数)中统计不同程序语言的票数并按照得票的顺序显示
原始数据
val votes = Seq(("scala", 7), ("java", 4), ("scala", 10), ("scala", 1), ("python", 10), ("python", 5))
分步操作:
1. 按语言名,把投票结果分组
val groupByLang = votes.groupBy(_._1)
此时输出 groupByLang:
Map(scala -> List((scala,7), (scala,10), (scala,1)), python -> List((python,10), (python,5)), java -> List((java,4)))
2. 统计每个分组的结果
val countVotes = groupByLang. map { case (which, counts) =>
(which, counts.foldLeft(0)(_ + _._2))
}
此时输出countVotes:
Map(scala -> 18, python -> 15, java -> 4)
3. 转Map为Seq,排序,反转
val finalList = countVotes.toSeq.sortBy(_._2).reverse.toList
此时输出 finalList:
List((scala,18), (python,15), (java,4))
合并在一起,简结明了:
val finalList = votes.groupBy(_._1)
.map { case (which, counts) =>
(which, counts.foldLeft(0)(_ + _._2))
}.toSeq
.sortBy(_._2)
.reverse.toList
这里,foldLeft 也是Scala Seq提供的一个方法:
-----------------------------------------------------------------------------------------------------------
def foldLeft[B](z: B)(op: (B, A) ⇒ B): B
Applies a binary operator to a start value and all elements of this sequence, going left to right.
----------------------------------------------------------------------------------------------------------------------------
举个例子:
设 testList((scala,7), (scala,10), (scala,1))
teestList.foldLeft(0)(_ + _._2)) 的结果 是 18.
Scala的 集合, Seq,Set,Map都提供了许多有用的方法, 而且可以链式调用。
具体视需求查Scala 的Api:
http://www.scala-lang.org/api/2.10.3/#package
Applies a binary operator to a start value and all elements of this sequence, going left to right.
Note: will not terminate for infinite-sized collections.
the result type of the binary operator.
the start value.
the binary operator.
the result of inserting
op
between consecutive elements of this sequence, going left to right with the start valuez
on the left:where
x1, ..., xn
are the elements of this sequence.