我有以下代码,我需要多次输入x._1.
和x._2.
。
case class T (Field1: String, Field2: Int, ....)
val j: DataSet[(T, T)] = ...
j.filter(x => x._1.Field1 == x._2.Field1
&& x._1.Field2 == x._2.Field2
&& ....)
这是一种将x
分解为(l, r)
的方法,因此表达式可以更短一些吗?
以下内容并不适用于Spark的DataSet。为什么? Spark的DataSet如何不支持Scala的语言构造?
filter{ case (l,r) => ...
在F#中,您可以编写类似
的内容j.filter((l, r) -> ....)
甚至
j.filtere(({Field1 = l1; Field2 = l2; ....}, {Field1 = r1; Field2 = r2; ....}) -> ....)
答案 0 :(得分:1)
诀窍是使用PartialFunction[A,B]
是Function1[A,B]
的子类的事实,因此,您可以在任何地方使用部分函数语法,预期Function1
(filter
,map
,flatMap
等。):
j.filter {
case (l,r) if (l.Field1 == lr.Field1 && l.Field2 == r.Field2 => true
case _ => false
}
更新
正如评论中所提到的,遗憾的是这不适用于spark Dataset
。这似乎是由于filter
在Dataset
中被重载,并且抛出了typer(在scala中通常不鼓励方法重载并且与其他功能不能很好地工作)
解决此问题的方法是定义一个具有不同名称的方法,您可以使用隐式转换在Dataset
上进行处理,然后使用该方法代替filter
:
object PimpedDataset {
implicit class It[T](val ds: Dataset[T]) extends AnyVal {
def filtered(f: T => Boolean) = ds.filter(f)
}
}
...
import PimpedDataset._
j.filtered {
case (l,r) if (l.Field1 == r.Field1 && l.Field2 == r.Field2 => true
case _ => false
}
这将编译......
答案 1 :(得分:1)
Spark的Dataset
类有多个重载filter(...)
方法,编译器无法推断使用哪个方法。你可以明确指定函数类型,但它有点难看。
j.filter({
case (l, r) => true
}: ((Field1, Field2)) => Boolean)
RDD
s仍然可以使用该语法(未明确指定类型)。不幸的是,为了支持Python / R / Etc,Spark开发人员决定放弃那些喜欢编写惯用Scala的用户。 :(