如何在Scala上使用Reduce

时间:2014-03-03 18:04:45

标签: scala

我正在使用scala来实现算法。我有一个案例需要实现这样的场景:

test = Map(t -> List((t,2)), B -> List((B,3), (B,1)), D -> List((D,1)))

我需要一些每个常见元组的第二个成员。

期望的结果:

Map((t,2),(B,4),(D,1))

val resReduce = test.foldLeft(Map.empty[String, List[Map.empty[String, Int]]){(count, tup) => count + (tup -> (count.getOrElse(tup, 0) + 1))

我正在尝试使用“减少”,我必须经历我所做的每一个小组并总结他们的第二个成员。不知道怎么做。

4 个答案:

答案 0 :(得分:3)

如果您知道所有列表都是非空的并且以相同的键开头(例如它们是由groupBy生成的),那么您可以

test.mapValues(_.map(_._2).sum).toMap

或者,您可能需要一个允许您执行错误检查的中间步骤:

test.map{ case(k,xs) =>
  val v = {
    if (xs.exists(_._1 != k)) ???   // Handle key-mismatch case
    else xs.reduceOption((l,r) => l.copy(_2 = l._2 + r._2))
  }
  v.getOrElse(??? /* Handle empty-list case */)
}

答案 1 :(得分:1)

你可以这样做:

 test collect{
   case (key, many) => (key, many.map(_._2).sum)
 }

其中您不必假设该列表包含任何成员。但是,如果要排除空列表,请添加一个警卫

   case (key, many) if many.nonEmpty =>
像那样。

答案 2 :(得分:0)

scala> val test = Map("t" -> List(("t",2)), "B" -> List(("B",3), ("B",1)), "D" -> List(("D",1)))
test: scala.collection.immutable.Map[String,List[(String, Int)]] = Map(t -> List((t,2)), B -> List((B,3), (B,1)), D -> List((D,1)))


scala> test.map{case (k,v) => (k, v.map(t => t._2).sum)}
res32: scala.collection.immutable.Map[String,Int] = Map(t -> 2, B -> 4, D -> 1)

答案 3 :(得分:0)

另一种方法,实质上与已经提出的方法非常相似,

implicit class mapAcc(val m: Map[String,List[(String,Int)]]) extends AnyVal {
  def mapCount() = for ( (k,v) <- m ) yield { (k,v.map {_._2}.sum) }
}

然后是给定的

val test = Map("t" -> List(("t",2)), "B" -> List(("B",3), ("B",1)), "D" -> List(("D",1)))

致电

test.mapCount()

递送

Map(t -> 2, B -> 4, D -> 1)