我编写了以下代码行,以从数据帧中的列中过滤出NULLS
df = df.where(col("colname").isNotNull)
这是正确的方法吗?
我还遇到了下面的代码行,以实现相同的结果:
df = df.filter($"colname".isNotNull)
现在我想了解的是 $ 运算符的用途是什么,哪种方法更好? 我还能在下面写这样的东西吗?
df = df.filter(col("colname").isNotNull)
我对Scala和编程领域还是很陌生,希望能对您有所帮助!
答案 0 :(得分:3)
有一个名为StringContext
的特殊Scala类。它用于实现各种字符串插值方法,例如
s"foo ${42}"
(导致String
"foo 42"
)或
f"foo ${42}%04x"
(这会导致String
具有十六进制格式的整数"foo 002a"
)。
该机制实际上非常通用,它允许您通过将StringContext
隐式转换为您自己的包装器类来定义各种不同的字符串插值机制。也就是说,如果需要,您可以定义如下所示的字符串插值机制:
myStringInterpolator"foo ${42}"
由于$
只是一个普通的标识符,因此您可以实现一个StringContext
包装器,该包装器具有带有签名的方法
def $(args: Any*): YourResultType
,并且此包装器进入隐式范围后,就可以使用$
进行字符串插值,如下所示:
$"some string literal ${arg1} more text ${arg2} end"
这将使用StringContext
持有["some string literal ", " more text ", " end"]
来构造包装器,然后使用$
和arg1
调用您的arg2
方法。
例如,您可以定义一个字符串插值$
,它将所有参数转换为整数并将它们求和:
implicit class MyDollarContext(s: StringContext) {
def $(args: Any*): Int = args.map(_.toString.toInt).sum
}
println($"I bought a coffee for ${30} and a snack for ${12}.")
这将打印42
,它是${...}
括号内所有数字的总和。
类似地,Apache Spark使用隐式StringToColumn
类将Strings
转换为Spark ColumnName
。我不确定为什么要以这种方式实现它,我想他们想使列名看起来有点像Perl或Bash变量,并为此使用了很多语法技巧。
答案 1 :(得分:1)
在这种情况下,两种用法都可以,因为您没有访问字符串内部的变量/值。
我相信美元符号通常用于字符串插值。这意味着如果我想在字符串内使用val(ue)/ var(iable)(在第一个双引号前用s
表示),我可以使用{{ 1}}号。否则,我们将无法在字符串内使用vals / vars,因为它将不知道如何转义字符串字符。
示例:
$
val favoriteFruit = "strawberry"
val strawberryCount = 12
println(s"My favorite fruit is ${favoriteFruit}. I've had ${strawberryCount} pieces today!") // string interpolation
也可用作$
方法的快捷方式。在某些情况下,如果您希望参数不总是具有对应的值,则可以使用getOrDefault设置默认值。 Source Example