我正在尝试使用scala从一列数据初始化Spark中的列表。某些行中的值可以为空,并且在某些行中它的值已填充。所以我正在制作Option[String]
类型的列表。但是,当我访问其中的元素时,scala会为每个元素返回Some
,包括空值,即使它们已使用Option(null)
初始化。这意味着当我尝试将值设为getOrElse("0")
时,如果值应为" 0"则会打印Some()
。在代码中,这就是我正在做的事情:
val columnsToRead: List[String] = List("__id", "device");
val selectedColumnsDataset: Array[List[(String, Option[String])]] =
dataset.map(s => {columnsToUseForCorrelation
.map(t => (t, Option(s.getAs[String](t))))
}).collect();
我确认,如果s.getAs[String](t)
不在行中,则表达式t
会返回null,方法是编写此备用地图
val selectedColumnsDataset2: Array[List[(String, Option[String])]] =
dataset.map(s => {columnsToUseForCorrelation
.map(t => (t, s.getAs[String](t)))
.map(t => (t._1, if (t._2 == null) Option(null) else Option(t._2)))
}).collect();
这两个表达式都返回相同的输出,所以我认为我正确地做了。我遇到的问题是当我尝试在这里打印出值时。我要做的第一件事就是将list
转换为wrappedarray
,我不明白隐式转换发生的位置,但如果我在地图上做了一个地图就会引发异常名单。这是我打印出这些值的代码:
val selectedColumnsParsed = selectedColumnsDataset.asInstanceOf[Array[mutable.WrappedArray.ofRef[(String, Option[String])]]];
selectedColumnsParsed.foreach(s => {
s.foreach(t => {
println(t._2.getOrElse("0"), t._2)
})
})
我从中获得的输出是
(440,Some(440))
(157,Some(157))
(441,Some(441))
(,Some())
(,Some())
(443,Some(443))
(,Some())
空值显示它们是空的,因此它们应该自动转换为None
类型,但它们是Some
类型,我不明白它们是怎样的他们不应该Some(null)
。字符串看起来像是空的长度为0,但是在println语句中调用isEmpty
会抛出空指针异常,这意味着getOrElse
应该返回默认值0
,但是它没有那样做。初始化Option
类型以使null
与None
类型匹配的正确方法是什么?
答案 0 :(得分:1)
某些行中的值可以为空
空(空白)与null
:
"".isEmpty
// Boolean = true
"" == null
// Boolean = false
因此Option
为空字符串,不是None
:
Option("")
// Option[String] = Some()
我首先要做的一件事是将列表转换为wrappedarray,我不明白隐式转换发生在哪里,
这是因为Dataset
中存储的数据已被编码。我们不依赖于具体的实现,而是依赖于接口。在这里你应该使用Seq
。
为了保持清洁,我会选择更简单的东西:
import org.apache.spark.sql.functions._
val columnsToRead: List[String] = List("__id", "device");
val dataset = Seq(
("foo", null, 0), // Here we expect None
("bar", "", -1), // Here we expect Some("")
("xyz", "zyx", 1)
).toDF("__id", "device", "some_val")
dataset
.select(array(columnsToRead map col: _*))
.as[Seq[Option[String]]]
.map(columnsToRead.zip(_))
.collect.foreach(println)
// List((__id,Some(foo)), (device,None))
// List((__id,Some(bar)), (device,Some()))
// List((__id,Some(xyz)), (device,Some(zyx)))
或
dataset
.select(columnsToRead map(c => struct(lit(c), col(c))): _*)
.as[((String, Option[String]), (String, Option[String]))]
.collect.foreach(println)
// ((__id,Some(foo)),(device,None))
// ((__id,Some(bar)),(device,Some()))
// ((__id,Some(xyz)),(device,Some(zyx)))
如果您希望空字符串为None
,则必须明确处理此字符串。