如何在列表中使用Column.isin?


71
val items = List("a", "b", "c")

sqlContext.sql("select c1 from table")
          .filter($"c1".isin(items))
          .collect
          .foreach(println)

上面的代码引发以下异常。

Exception in thread "main" java.lang.RuntimeException: Unsupported literal type class scala.collection.immutable.$colon$colon List(a, b, c) 
at org.apache.spark.sql.catalyst.expressions.Literal$.apply(literals.scala:49)
at org.apache.spark.sql.functions$.lit(functions.scala:89)
at org.apache.spark.sql.Column$$anonfun$isin$1.apply(Column.scala:642)
at org.apache.spark.sql.Column$$anonfun$isin$1.apply(Column.scala:642)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
at scala.collection.mutable.WrappedArray.foreach(WrappedArray.scala:35)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
at scala.collection.AbstractTraversable.map(Traversable.scala:104)
at org.apache.spark.sql.Column.isin(Column.scala:642)

以下是我修复它的尝试。它编译并运行,但不返回任何匹配项。不知道为什么。

val items = List("a", "b", "c").mkString("\"","\",\"","\"")

sqlContext.sql("select c1 from table")
          .filter($"c1".isin(items))
          .collect
          .foreach(println)

Answers:


131

根据文档,isin需要一个变量,而不是列表。List实际上是一个令人困惑的名称。您可以尝试将List转换为vararg,如下所示:

val items = List("a", "b", "c")

sqlContext.sql("select c1 from table")
          .filter($"c1".isin(items:_*))
          .collect
          .foreach(println)

带有mkString的变量会进行编译,因为一个String也是一个vararg(参数数量等于1),但这并不是您想要实现的。


17

它在Java Api(Java 8)中像这样工作

.isin(sampleListName.stream().toArray(String[]::new))));

sampleListName是一个列表


5

从2.4.0版本开始,Spark现在拥有一个名为的方法isInCollection,这正是您要寻找的方法,而不是isIn

(他们不应该统一方法吗?)


2

正如Tomalak提到的那样:

isin(java.lang.Object... list)
A boolean expression that is evaluated to true if the value 
of this expression is contained by the evaluated values of the arguments.

因此,您只需进行以下更改即可解决此问题:

val items = List("a", "b", "c").map(c => s""""$c"""")

1
为什么要地图?我的.filter($"c1".isin(List("a", "b", "c")))想法是可行的。
Tomalak 2015年

考虑到您的代码List("a", "b", "c").mkString("\"","\",\"","\""),我假设您想用双引号将每个项目引起来。地图做同样的事情。
弗朗西斯·托斯

0

更简单:

sqlContext.sql("select c1 from table")
          .filter($"c1".isin("a", "b", "c"))
          .collect
          .foreach(println)

除非您有很多列表值,否则通常不是这种情况。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.