foldLeft on Iterable(String, (Long, Long))
foldLeft on Iterable(String, (Long,Long))
所以。场景:
我有这样的列表:
("USER1",(24,11))
("USER2",(10,7))
("USER2",(1,10))
("USER1",(2,3))
("USER3",(3,4))
我需要groupBy
每个用户的所有信息,然后对每个元组的信息求和。
所以我的预期输出是:
("USER1",(26,14))
("USER2",(11,17))
("USER3",(3,4))
我用下面的代码实现了这个:
userInfo.groupBy(elem => elem._1).map(_._2).map { user =>
{
val sums = user.foldLeft(("", (0L, 0L)))((acc, newElem) =>
(acc._1,
(acc._2._1 + newElem._2._1, acc._2._2 + newElem._2._2)))
}
(user._1,sums)
}
其中 userInfo
是 Iterable[String,(Long,Long)]
如您所见,我使用了 foldLeft,我几乎忽略了每个元组的第一个元素,因为我并不真正关心 foldLeft。
我想知道,因为我发现它的代码非常糟糕,主要是因为这个 foldLeft
有一个空字符串,有没有更好的解决方案?
也许这个,你可以在这种情况下使用 reduce 而不是 foldLeft:
def sumOp(x: (Int, Int), y: (Int, Int)): (Int, Int) = (x._1 + y._1, x._2 + y._2)
userInfo.groupBy(_._1).mapValues(user => user.map{ case (u, x) => x }.reduce(sumOp))
// res52: scala.collection.immutable.Map[String,(Int, Int)] = Map(USER2 -> (11,17), USER1 -> (26,14), USER3 -> (3,4))
使用mapValues
和一个简单的reduce
:
val res: Map[String, (Int, Int)] =
userInfo
.groupBy { case (user, _) => user }
.mapValues { it: Iterable[(String, (Int, Int))] =>
it
.map { case (_, tuple) => tuple }
.reduce[(Int, Int)] { case ((a, b), (c, d)) => (a + c, b + d) }
}
所以。场景:
我有这样的列表:
("USER1",(24,11))
("USER2",(10,7))
("USER2",(1,10))
("USER1",(2,3))
("USER3",(3,4))
我需要groupBy
每个用户的所有信息,然后对每个元组的信息求和。
所以我的预期输出是:
("USER1",(26,14))
("USER2",(11,17))
("USER3",(3,4))
我用下面的代码实现了这个:
userInfo.groupBy(elem => elem._1).map(_._2).map { user =>
{
val sums = user.foldLeft(("", (0L, 0L)))((acc, newElem) =>
(acc._1,
(acc._2._1 + newElem._2._1, acc._2._2 + newElem._2._2)))
}
(user._1,sums)
}
其中 userInfo
是 Iterable[String,(Long,Long)]
如您所见,我使用了 foldLeft,我几乎忽略了每个元组的第一个元素,因为我并不真正关心 foldLeft。
我想知道,因为我发现它的代码非常糟糕,主要是因为这个 foldLeft
有一个空字符串,有没有更好的解决方案?
也许这个,你可以在这种情况下使用 reduce 而不是 foldLeft:
def sumOp(x: (Int, Int), y: (Int, Int)): (Int, Int) = (x._1 + y._1, x._2 + y._2)
userInfo.groupBy(_._1).mapValues(user => user.map{ case (u, x) => x }.reduce(sumOp))
// res52: scala.collection.immutable.Map[String,(Int, Int)] = Map(USER2 -> (11,17), USER1 -> (26,14), USER3 -> (3,4))
使用mapValues
和一个简单的reduce
:
val res: Map[String, (Int, Int)] =
userInfo
.groupBy { case (user, _) => user }
.mapValues { it: Iterable[(String, (Int, Int))] =>
it
.map { case (_, tuple) => tuple }
.reduce[(Int, Int)] { case ((a, b), (c, d)) => (a + c, b + d) }
}