将TraversableOnce [T]变成Multiset-like或Histogram-ish Map [T,Int]的最简洁方法是什么?

时间:2013-03-28 19:57:53

标签: scala multiset

我想将Traversable [T]转换为带有计数的Map [T,Int]直方图。我希望结果是一个不可变的Map,它匹配我所做的事情:

traversable.groupBy(_).mapValues(_.length)

但看起来这不是空间或时间效率的......因为groupBy维护了对遍历中每个元素的引用,所以对于具有一小组唯一键的大型遍历,它的性能很差。我真的想要更像这样的东西:

def histogram[T](ts : Traversable[T]) : Map[T, Int] = {
  val map = new collection.mutable.HashMap[T, Int].withDefaultValue(0)
  ts.foreach { map(_) += 1 }
  map.toMap
}

是否有一个库方法可以为我提供此结果(理想情况下,可以很好地处理并行集合)?

3 个答案:

答案 0 :(得分:1)

这是我的扩展程序,与您的建议非常相似:

implicit final class RichIterable[A](val it: TraversableOnce[A]) extends AnyVal {
  def histogram: Map[A, Int] = {
    var res = Map.empty[A, Int] withDefaultValue 0
    it.foreach { elem =>
      res += elem -> (res(elem) + 1)
    }
    res
  }
}

不一定是最快的解决方案,但简洁明了:)

答案 1 :(得分:1)

t.foldLeft(Map.empty[Int, Int].withDefaultValue(0)) { (acc, i) => acc.updated(i, acc(i) + 1) }

答案 2 :(得分:0)

我会考虑使用直方图函数对遍历进行遍历。创建一个隐式类,将“toHistogram [T]”添加到遍历。我不认为标准库中存在功能。