Scala 如何找到距离最小的RDD

Scala 如何找到距离最小的RDD,scala,apache-spark,rdd,analysis,Scala,Apache Spark,Rdd,Analysis,我已经创建了这种类型的RDD: RDD[(Long, Iterable[(String, Double)])] 这里,第一个长参数是地图中原始点的ID,第二个字符串参数是另一个点的ID,该点在一个固定数据集中以字符串格式表示。第三个参数Double是两点之间的距离 现在,我想找到给定点的最小距离点。所以,我想把这个RDD转换成RDD[(长,(字符串,双精度))]。因此,我将得到所有最接近给定点集的点 我现在的输出是这样的 (4516831,CompactBuffer((POI1,2632.06

我已经创建了这种类型的RDD:

RDD[(Long, Iterable[(String, Double)])]
这里,第一个长参数是地图中原始点的ID,第二个字符串参数是另一个点的ID,该点在一个固定数据集中以字符串格式表示。第三个参数Double是两点之间的距离

现在,我想找到给定点的最小距离点。所以,我想把这个
RDD
转换成
RDD[(长,(字符串,双精度))]
。因此,我将得到所有最接近给定点集的点

我现在的输出是这样的

(4516831,CompactBuffer((POI1,2632.0690038389157), (POI2,2632.0690038389157), (POI3,666.9416656643995), (POI4,1450.3241112528403)))
(4516915,CompactBuffer((POI1,2632.0690038389157), (POI2,2632.0690038389157), (POI3,666.9416656643995), (POI4,1450.3241112528403)))
我试图写的代码是这样的

`
// groupData returns output in the format RDD[(Long, (String, Double))]
val combinedData = groupData(dataRdd, poiRdd)
  .groupByKey()
  .map(row => {
    var min:Double = 9999999
    for(value <- row._2) yield
      if (value._2 < min) {
        min = value._2
      } else min
  (row._1, row._2.filter(r => r._2 == min))
  }).foreach(println)
// output like this: (4516915,List((POI3,666.9416656643995)))`
`
//groupData以RDD[(长,(字符串,双精度))]格式返回输出
val combinedData=groupData(dataRdd,poiRdd)
.groupByKey()
.map(行=>{
最小变量:双精度=9999999
对于(值r._2==min))
}).foreach(println)
//如下输出:(4516915,列表((POI3666.9416656643995)))`
上面的代码按照要求可以很好地工作,但我认为它真的很糟糕,特别是在最后一行中,我返回了我想要的输出。我又开始过滤了。 一定有更好的办法。 我怎样才能做到这一点?如果这个问题有点含糊,我很抱歉


谢谢。

我认为您的示例输入数据是来自
groupByKey
的中间数据。如果是这样,假设您的原始RDD如下所示:

val rdd = sc.parallelize(Seq(
  (4516831, ("POI1", 2632.0690038389157)),
  (4516831, ("POI2", 2632.0690038389157)),
  (4516831, ("POI3", 666.9416656643995)),
  (4516831, ("POI4", 1450.3241112528403)),
  (4516915, ("POI1", 2632.0690038389157)),
  (4516915, ("POI2", 2632.0690038389157)),
  (4516915, ("POI3", 666.9416656643995)),
  (4516915, ("POI4", 1450.3241112528403))
))

val groupedRDD = rdd.groupByKey
// groupedRDD: org.apache.spark.rdd.RDD[(Int, Iterable[(String, Double)])] = ...
val resultRDD2 = rdd.reduceByKey(
    (acc, x) => if (x._2 < acc._2) x else acc
  ).map{ case (k, v) => (k, List(v))}

resultRDD2.collect
// res2: Array[(Int, List[(String, Double)])] = Array(
//   (4516915,List((POI3,666.9416656643995))), (4516831,List((POI3,666.9416656643995)))
// )
然后,
groupedRDD
应具有与示例输入数据完全相同的数据

然后,您可以使用
reduce
处理groupedRDD的
mapValues
以捕获最小值,并根据您的输出要求将简化后的结果包装在
列表中:

val resultRDD1 = groupedRDD.mapValues( _.reduce{
    (acc, x) => if (x._2 < acc._2) x else acc
  }).map{ case (k, v) => (k, List(v))}

resultRDD1.collect
// res1: Array[(Int, List[(String, Double)])] = Array(
//   (4516915,List((POI3,666.9416656643995))), (4516831,List((POI3,666.9416656643995)))
// )

似乎是一个简单的
map
函数,带有
min
应该可以工作。你试过什么?你被卡在哪里了?您是否有任何代码或密码可以提供。嗨,pault,谢谢您的回复。我已经更新了问题以便更好地理解。如果答案回答了您的问题,请接受它以结束问题嗨,利奥,谢谢您的回答。我已经印了一些例子。我需要最终输出,因为我只需要更干净的代码。@Piyush P,我明白了,您希望最小值的元素包装在
列表中。请看我修改过的答案。