在Spark中使用x.head, x.tail: _*的原因



我想改变数据框中列的顺序,并发现正确的方法如下:val reorderedColumnNames: Array[String] = ??? // the new order of columns

val result: DataFrame = dataFrame.select(reorderedColumnNames.head, reorderedColumnNames.tail: _*)

我的问题是:为什么不能像下面这样使用冒号": _*"应该让你的集合(Seq,列表或数组)的所有元素?val result: DataFrame = dataFrame.select(reorderedColumnNames: _*)

我不明白为什么第二种方式不被Spark接受(并产生错误),因为两种方式都应该是等效的

Dataset的API要求这样做

首先,Dataframe(据我回忆,从2.0开始,或多或少)在实现方面只是Dataset[Row],所以你必须检查Dataset的API文档。

看看select方法,有两种实现可供选择。

def select(col: String, cols: String*): DataFrame 

它接受一个String,后跟任意数量的String

def select(cols: Column*): DataFrame 

这个可以接受任意数量的Column实例。

示例代码:val reorderedColumnNames: Array[String]是一个字符串数组。因此,您只能使用该方法的字符串变体,这需要使用至少一个String参数,后面可能还有其他参数。这就是为什么你不能直接扩展你的数组

如果您要将Array[String]转换为Array[Column],它将工作,即:

val reorderedColumnNamesAsCols: Array[Column] = reorderedColumnNames.map(col(_))
dataFrame.select(reorderedColumnNamesAsCols: _*)

现在为什么不提出一个select(cols: String*)的变体呢?我不知道这是否/为什么被提出,但我猜测它不会被编译器很好地发挥作用。我们可以检查:

scala> class Test {
|   def test(strs: String*): Unit = {}
|   def test(nbrs: Integer*): Unit = {}
| }
<console>:13: error: double definition:
def test(strs: String*): Unit at line 12 and
def test(nbrs: Integer*): Unit at line 13
have same type after erasure: (strs: Seq)Unit
def test(nbrs: Integer*): Unit = {}
^

编译器不满意

最新更新