情景设定:
从一组投票结果(语言,票数)中统计不同程序语言的票数并按照得票的顺序显示
原始数据
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.
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.
B
the result type of the binary operator.
z
the start value.
op
the binary operator.
returns
the result of inserting op between consecutive elements of this sequence, going left to right with the start value z on the left:
op(...op(z, x_1), x_2, ..., x_n)
where x1, ..., xn are the elements of this sequence.
----------------------------------------------------------------------------------------------------------------------------
举个例子:
设 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