Scala - 计算迭代器中每个键的出现次数

时间:2015-10-25 21:01:28

标签: scala iterator

我有一个包含一些键值对的迭代器。 例如

  

(jen,xyz)(ken,zxy)(jen,asd)(ken,asdf)

结果应为

  

(jen,2)(ken,2)

如何使用count函数(或任何其他函数)计算该特定集合的迭代器中每个键的出现次数。

修改 这个迭代器在我的用例中代表的集合有大量的记录,可能在数百万的范围内,我不需要最有效(时间复杂度较低)的方法来做到这一点。我发现默认的计数方法非常快,并且它可能以某种方式用于产生所需的结果。

2 个答案:

答案 0 :(得分:10)

Peter Neyens建议的方法可行,但由于使用toListgroupBylength的方式,某些应用程序可能效率非常低(时间和内存) 。将计数直接聚合到地图中通常会更有效率,并避免所有不必要的Lists创建。

import scala.collection.TraversableOnce
import scala.collection.mutable.HashMap

def counts[T](xs: TraversableOnce[T]): Map[T, Int] = {
  xs.foldLeft(HashMap.empty[T, Int].withDefaultValue(0))((acc, x) => { acc(x) += 1; acc}).toMap
}

一旦定义了counts方法,就可以将它应用到键值对的迭代器中,如下所示:

val iter: Iterator[(String, String)] = ???
val keyCounts = counts(iter.map(_._1))

上面定义的counts方法适用于大量值的Iterators,例如

val iter = Iterator.range(0, 100000000).map(i => (i % 1931, i))
val countMap = counts(iter.map(_._1))
// Map(645 -> 51787, 892 -> 51787, 69 -> 51787, 1322 -> 51786, ...)

工作得很好,而在Peter的答案中提出的方法,即

val iter = Iterator.range(0, 100000000).map(i => (i % 1931, i))
val countMap = iter.toList.groupBy(_._1).mapValues(_.length).toMap

突然离开一段时间,最终导致OutOfMemoryError。它失败的原因是因为所有不必要的List创建。

答案 1 :(得分:5)

您可以groupBy密钥,然后计算每个密钥的出现次数:

val iterator = 
  Iterator(("jen","xyz"), ("ken","zxy"), ("jen","asd"), ("ken", "asdf"))

iterator.toList.groupBy(_._1).mapValues(_.length).toList
// List[(String, Int)] = List((jen,2), (ken,2))