Scala 在同组RDD上迭代

Scala 在同组RDD上迭代,scala,apache-spark,Scala,Apache Spark,我使用了一个cogroup函数并获得了以下RDD: org.apache.spark.rdd.RDD[(Int, (Iterable[(Int, Long)], Iterable[(Int, Long)]))] 在映射操作之前,连接的对象将如下所示: RDD[(Int, (Iterable[(Int, Long)], Iterable[(Int, Long)]))] (-2095842000,(CompactBuffer((1504999740,1430096464017), (613904

我使用了一个cogroup函数并获得了以下RDD:

org.apache.spark.rdd.RDD[(Int, (Iterable[(Int, Long)], Iterable[(Int, Long)]))]
在映射操作之前,连接的对象将如下所示:

RDD[(Int, (Iterable[(Int, Long)], Iterable[(Int, Long)]))]

(-2095842000,(CompactBuffer((1504999740,1430096464017), (613904354,1430211912709), (-1514234644,1430288363100), (-276850688,1430330412225)),CompactBuffer((-511732877,1428682217564), (1133633791,1428831320960), (1168566678,1428964645450), (-407341933,1429009306167), (-1996133514,1429016485487), (872888282,1429031501681), (-826902224,1429034491003), (818711584,1429111125268), (-1068875079,1429117498135), (301875333,1429121399450), (-1730846275,1429131773065), (1806256621,1429135583312))))
(352234000,(CompactBuffer((1350763226,1430006650167), (-330160951,1430320010314)),CompactBuffer((2113207721,1428994842593), (-483470471,1429324209560), (1803928603,1429426861915))))
现在我想做以下工作:

val globalBuffer = ListBuffer[Double]()
val joined = data1.cogroup(data2).map(x => {
  val listA = x._2._1.toList
  val listB = x._2._2.toList
  for(tupleB <- listB) {
    val localResults = ListBuffer[Double]()
    val itemToTest = Set(tupleB._1)
    val tempList = ListBuffer[(Int, Double)]()
    for(tupleA <- listA) {
      val tValue = someFunctionReturnDouble(tupleB._2, tupleA._2)
      val i = (tupleA._1, tValue)
      tempList += i
    }
    val sortList = tempList.sortWith(_._2 > _._2).slice(0,20).map(i => i._1)
    val intersect = sortList.toSet.intersect(itemToTest)
    if (intersect.size > 0)
      localResults += 1.0
    else localResults += 0.0
    val normalized = sum(localResults.toList)/localResults.size
    globalBuffer += normalized
  }
})

//method sum
def sum(xs: List[Double]): Double = {//do the sum}
val globalBuffer=ListBuffer[Double]()
val joined=data1.cogroup(data2.map)(x=>{
val listA=x.。\u 2.\u 1.toList
val listB=x._2._2.toList
用于(元组i.。_1)
val intersect=sortList.toSet.intersect(itemToTest)
如果(intersect.size>0)
localResults+=1.0
else localResults+=0.0
val normalized=sum(localResults.toList)/localResults.size
globalBuffer+=标准化
}
})
//方法和
def sum(xs:List[Double]):Double={//do the sum}

在这篇文章的结尾,我希望加入的是一个具有双值的列表。但当我看到它时,它是一个单位。我也会说,这不是Scala的做法。如何获得
globalBuffer
作为最终结果。

Hmm,如果我正确理解了您的代码,它将从以下改进中受益:

val joined = data1.cogroup(data2).map(x => {
  val listA = x._2._1.toList
  val listB = x._2._2.toList
  val localResults = listB.map { 
    case (intBValue, longBValue) =>
    val itemToTest = intBValue // it's always one element
    val tempList = listA.map {
       case (intAValue, longAValue) =>
       (intAValue, someFunctionReturnDouble(longBvalue, longAValue))
    }
    val sortList = tempList.sortWith(-_._2).slice(0,20).map(i => i._1)
    if (sortList.toSet.contains(itemToTest)) { 1.0 } else {0.0}
// no real need to convert to a set for 20 elements, by the way
  }
  sum(localResults)/localResults.size
})

rdd
的转换不会修改
globalBuffer
。创建了
globalBuffer
的副本并发送给每个工人,但是工人对这些副本的任何修改都不会修改驱动程序上存在的
globalBuffer
(您在
RDD
上的
映射
之外定义的副本)。以下是我要做的(还有一些额外的修改):

val joined=data1.cogroup(data2)映射{x=>
val iterA=x.。\u 2.\u 1
val iterB=x.。\u 2.\u 2
变量计数,正计数=0
val templast=ListBuffer[(整数,双精度)]()

对于(tupleB@Null-Hypothesis),你能澄清一下你在之前的评论中的意思吗?你的意思是你在“循环”时想要某种连续的比例吗请进一步澄清。@Null假设是的,它在Scala中有效:函数体中最后一条指令的结果成为该函数返回的值。它将是RDD[Double],如果需要,您必须将其转换为一个列表。@Null假设,那么对于每个x,您需要一个单一的比例?如果,那么我认为Ashalynd或我的方法(对于一些小细节,它们几乎是相同的模)很好。你只需要做一个
连接。收集
来获得一个本地收集,假设这是你最终想要的。@Null假设,忘记
全局缓冲区
。请参阅我关于为什么这不起作用的答案。Ashalynd或我的代码创建的
RDD
连接
将包含你想要的所有比例。如果您想在本地
数组中使用它,那么只需使用val
localJoined=joined.collect
。如果您需要在
列表中使用它,那么请使用
val localJoined=joined.collect.toList
。或者您可以将.collect.toList添加到joined的定义中,如果您愿意的话。@Null假设,请参阅代码前面的注释--a transforma a
RDD
上的操作无法修改驱动程序上任何对象的状态(除非您使用的是
累加器/可累加器
,在这种情况下,您不…我不建议这样做。)@如果您不知道,则为空假设(如果您知道,请原谅我),在Scala中,最后计算的值是函数返回的值。因此,上面的函数(传递到
RDD
map
方法中)将每个
x
映射到
positiveCount.toDouble/count
。应用于此函数的
map
方法的结果将是包含这些比例的
RDD
val joined = data1.cogroup(data2) map { x =>
  val iterA = x._2._1
  val iterB = x._2._2
  var count, positiveCount = 0
  val tempList = ListBuffer[(Int, Double)]()
  for (tupleB <- iterB) {
    tempList.clear
    for(tupleA <- iterA) {
      val tValue = someFunctionReturnDouble(tupleB._2, tupleA._2)
      tempList += ((tupleA._1, tValue))
    }
    val sortList = tempList.sortWith(_._2 > _._2).iterator.take(20)
    if (sortList.exists(_._1 == tupleB._1)) positiveCount += 1
    count += 1
  }
  positiveCount.toDouble/count
}