【问题标题】:Scala Join Arrays and Reduce on ValueScala 加入数组并减少值
【发布时间】:2018-10-09 06:50:43
【问题描述】:

我有两个要加入的键/值对数组[(String, Int)],但仅在键匹配时才返回最小值。

val a = Array(("personA", 1), ("personB", 4), ("personC", 5))
val b = Array(("personC", 4), ("personA", 2))

目标:c = Array((personA, 1), (personC, 4))

val c = a.join(b).collect()

结果:c = Array((personA, (1, 2)), (personC, (5, 4)))

我尝试使用 join 方法实现此目的,但在将它们加入单个数组后减少值时遇到困难:Array[(String, (Int, Int))]

【问题讨论】:

  • 我突然想到 ab 可能是 Apache Spark PairRDD 集合,而不是 Arrays(因为 join 不是Scala Array 函数)。我相应地更新了我的答案。让我知道这是否适合您...

标签: arrays scala reduce


【解决方案1】:

试试这个:

val a = Array(("personA", 1), ("personB", 4), ("personC", 5))
val b = Array(("personC", 4), ("personA", 2))
val bMap = b.toMap
val cMap = a.toMap.filterKeys(bMap.contains).map {
  case(k, v) => k -> Math.min(v, bMap(k))
}
val c = cMap.toArray

toMap 方法将Array[(String, Int)] 转换为Map[String, Int];然后使用filterKeys 仅保留a.toMap 中也位于b.toMap 中的键(字符串)。然后map 操作为每个键选择两个可用值中的最小值,并创建一个将每个键与该最小值相关联的新映射。最后,我们使用toArray 将生成的地图转换回Array[(String, Int)]

更新

顺便说一句:我不确定你从哪里得到Array.join 方法:Array 没有这样的方法,所以a.join(b) 对我不起作用。但是,我怀疑 ab 可能是 Apache Spark PairRDD 集合(或类似的东西)。如果是这种情况,那么您可以加入 ab,然后将值映射到每对的最小值(reduce 操作不是您想要的),如下所示:

a.join(b).mapValues(v => Math.min(v._1, v._2)).collect

collect 根据需要将结果转换为Array[(String, Int)]

【讨论】:

  • 谢谢迈克。是的,它确实是一个允许加入语句的 PairRDD。是否可以在连接后将对象中的两个 Int 减少为单独的语句?
  • @SMC reduce 操作应用于整个集合,导致单个值(或错误,如果集合为空)。如果您将reduce 应用到RDD,您将获得一个值——您需要一个Array。如果您想知道是否可以将reduce 应用于 tuple,那么不,您不能。在一般情况下,元组不是同质的(例如,你可以有一个StringInt元组),而reduce可以只能在同质元素上执行。在您的情况下,您将[(String, (Int, Int))] 值变形为[(String, Int)],这是一个map 操作。
  • @SMC mapValues 是一个 PairRDD 优化,仅应用于每对的 。它比 keyvalue 上的 map 更简单、更高效。它还确保不会发生昂贵的重新分区。
  • 迈克艾伦 - 谢谢你的解释。很有帮助。
猜你喜欢
  • 2020-03-29
  • 2021-11-14
  • 2014-08-04
  • 2020-09-17
  • 1970-01-01
  • 1970-01-01
  • 2019-10-01
  • 1970-01-01
  • 2021-02-16
相关资源
最近更新 更多