我有一个包含一些键值对的迭代器。 例如
(jen,xyz)(ken,zxy)(jen,asd)(ken,asdf)
结果应为
(jen,2)(ken,2)
如何使用count函数(或任何其他函数)计算该特定集合的迭代器中每个键的出现次数。
修改 这个迭代器在我的用例中代表的集合有大量的记录,可能在数百万的范围内,我不需要最有效(时间复杂度较低)的方法来做到这一点。我发现默认的计数方法非常快,并且它可能以某种方式用于产生所需的结果。
答案 0 :(得分:10)
Peter Neyens建议的方法可行,但由于使用toList
,groupBy
和length
的方式,某些应用程序可能效率非常低(时间和内存) 。将计数直接聚合到地图中通常会更有效率,并避免所有不必要的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))