如何将 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 与列表一起使用?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 DiagnosticableTreeMixin 与列表一起使用?