如何将 Column.isin 与列表一起使用?

Posted

技术标签:

【中文标题】如何将 Column.isin 与列表一起使用?【英文标题】:How to use Column.isin with list? 【发布时间】:2015-09-13 16:32:16 【问题描述】:
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)

【问题讨论】:

【参考方案1】:

根据文档,isin 采用可变参数,而不是列表。列表在这里实际上是一个令人困惑的名称。您可以尝试将您的列表转换为可变参数,如下所示:

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

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

您的带有 mkString 的变体可以编译,因为单个 String 也是一个 vararg(参数数量等于 1),但它可能不是您想要实现的。

【讨论】:

【参考方案2】:

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

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

sampleListName 是一个列表

【讨论】:

【参考方案3】:

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

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

【讨论】:

请注意,此方法是通过:def isInCollection(values: scala.collection.Iterable[_]): Column = isin(values.toSeq: _*) 实现的(参见:definition)。我真的不知道为什么 API 有两个不同的名称来表示类似的行为。 这让我更加困惑。我真的不明白。我希望有一个重载方法来处理这两种类型的输入,就像 API 中的许多其他方法一样。谢谢你的信息! 这个PR介绍方法不用解释:/ @BlueSheepToken 讨论在this PR。它没有重载的原因是 isin 被定义为采用 Any*,而 Iterable[_] 可以是 Any* 导致冲突。 我不知道你们是怎么找到这种东西的,但是我的随机切线问题在我将其发布 20 个月后得到了完全回答。谢谢!【参考方案4】:

正如托马拉克所说:

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"""")

【讨论】:

为什么是地图?我的是 .filter($"c1".isin(List("a", "b", "c"))) 可以工作。 考虑到您的代码List("a", "b", "c").mkString("\"","\",\"","\""),我假设您想用双引号将每个项目括起来。地图做同样的事情。【参考方案5】:

更简单:

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

除非您有很多列表值,通常情况并非如此。

【讨论】:

以上是关于如何将 Column.isin 与列表一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

Spark的Column.isin函数不带List

如何将 DiagnosticableTreeMixin 与列表一起使用?

如何将列表视图与其他小部件一起使用?

如何将列表中的每个项目与Python中另一个列表的所有值一起使用[重复]

如何将 DSL.coalesce 与字段列表一起使用?

如何将 javascript 与 asp.net 下拉列表控件一起使用?