Scala 从返回类型为

Scala 从返回类型为,scala,apache-spark,spark-dataframe,rdd,variadic-functions,Scala,Apache Spark,Spark Dataframe,Rdd,Variadic Functions,我需要聚合3个不同的rdd(在3个不同的迭代中),我正在使用map调用一个函数createKeyValuePair,该函数的返回类型为[((Long,Int,Int),a),((Int,Int,Int,Int),a)] 但是,reduceByKey不可用,它表示无法解析reduceByKey def createKeyValuePair(row: Row, data: String, elementsInKey: Int) : Either[((Long, Int, Int), A),

我需要聚合3个不同的
rdd
(在3个不同的迭代中),我正在使用
map
调用一个函数
createKeyValuePair
,该函数的返回类型为[((Long,Int,Int),a),((Int,Int,Int,Int),a)]

但是,
reduceByKey
不可用,它表示
无法解析reduceByKey

def createKeyValuePair(row: Row, data: String, elementsInKey: Int) : Either[((Long, Int, Int), A),
                                                                    ((Int, Int, Int, Int, Int), A)] = {
    var keySet = Array[Long]()
    for (i <- 0 to elementsInKey) {
        keySet = keySet :+ row(i).asInstanceOf[Long]
    }
    val record = row(elementsInKey).asInstanceOf[A]
    dataCut match {
        case "string1" => return ... //(first key)
        case "string2" => return ... //(second key)
    }
    null
}
然后
reduceByKey
工作,但它认为返回类型只是
((Long,Int),A)
,函数也显示错误,返回类型预期是
(Long,Int)
,但实际是
Seq[A]

问题2。在scala中不能将返回类型设为varargs吗?
注意:
reduceByKey
将应用的返回类型和数据具有相同的模式。我没有试图对具有不同模式的数据应用
reduceByKey
。我将首先读取文件1和文件2,并将其聚合,其中键为
(Long,Int,Int)
,然后在第二次迭代中,将读取第二个文件,其中键为
(Int,Int,Int,Int)
,并将其聚合。
reduceByKey
仅适用于(键,值)对的RDD,而您实际上没有(因为它们被包装在
中)

一个选项是从
RDD[(Long,Int,Int),A),((Int,Int,Int,Int),A)]
更改为
RDD[(Long,Int,Int),(Int,Int,Int),A)]

但是,我不认为您应该有一个
createKeyValuePair
函数。在这两种情况下,您实际上共享的唯一代码是构建密钥数组。想象一下

def getKeyElements(row: Row, recordIndex: Int): List[Long] = {
  (0 until recordIndex).map(row.getLong).toList
}

def createKeyValuePairFirstCase(row: Row): ((Long, Int, Int), A) = {
  val first :: second :: third :: _ = getKeyElements(row, 3)
  ((first, second, third), row.get(3).asInstanceOf[A])
}
在第二种情况下也是如此,我相信(虽然我不确定也没有检查)您在键中得到了从
Long
Int
的隐式转换

一些随机注释:

  • 我们需要
    getKeyElements
    返回一个
    列表
    以使用第一个
第二个
第三个
,就像这样。您也可以只返回一个
Seq
并使用索引构建元组
  • 注意存在
    getLong
    。还有
    getInt
    getString
    等等
  • 它确实感觉应该有一种方法来参数化键的类型并编写一个函数,但我不知道它是什么
  • 您是否考虑过使用新的Dataset API?您也许可以使其更易于阅读,更健壮

  • 嘿,解释得很好。谢谢。
    我不认为你应该有一个createKeyValuePair
    。拥有一个函数的唯一原因是我想使用
    for
    循环对3个不同的文件进行相同的聚合。两个有
    Long,Int,Int
    ,一个有
    (Int,Int,Int,Int,Int)
    。我最后写了3篇不同的文章来阅读并汇总这3篇文章。
    def createKeyValuePair(row: Row, data: String, elementsInKey: Int) : ((Long*, Int*), A) = {
        var keySet = Array[Long]()
        for (i <- 0 to elementsInKey) {
            keySet = keySet :+ row(i).asInstanceOf[Long]
        }
        val record = row(elementsInKey).asInstanceOf[A]
    
        ((keySet: _*),record)
    }
    
    def getKeyElements(row: Row, recordIndex: Int): List[Long] = {
      (0 until recordIndex).map(row.getLong).toList
    }
    
    def createKeyValuePairFirstCase(row: Row): ((Long, Int, Int), A) = {
      val first :: second :: third :: _ = getKeyElements(row, 3)
      ((first, second, third), row.get(3).asInstanceOf[A])
    }