在Scala中,$符号的用途是什么?

时间:2018-09-28 12:04:48

标签: java scala dataframe null

我编写了以下代码行,以从数据帧中的列中过滤出NULLS

df = df.where(col("colname").isNotNull)

这是正确的方法吗?
我还遇到了下面的代码行,以实现相同的结果:

df = df.filter($"colname".isNotNull)

现在我想了解的是 $ 运算符的用途是什么,哪种方法更好? 我还能在下面写这样的东西吗?

df = df.filter(col("colname").isNotNull)

我对Scala和编程领域还是很陌生,希望能对您有所帮助!

2 个答案:

答案 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