我是一名python程序员,因为Python API对我的Spark应用程序来说太慢了,所以决定将我的代码移植到Spark Scala API,以比较计算时间。
我正在尝试使用Spark中的Scala API从一个巨大的文件中过滤掉以数字字符开头的行。在我的文件中,有些行有数字,有些有单词,我想要只有数字的行。
因此,在我的Python应用程序中,我有这些行。
l = sc.textFile("my_file_path")
l_filtered = l.filter(lambda s: s[0].isdigit())
完全符合我的要求。
这是我到目前为止所尝试过的。
val l = sc.textFile("my_file_path")
val l_filtered = l.filter(x => x.forall(_.isDigit))
这会抛出一个错误,说char没有forall()函数。
我也尝试使用s.take(1)获取行的第一个字符,并按以下方式对其应用isDigit()函数。
val l = sc.textFile("my_file_path")
val l_filtered = l.filter(x => x.take(1).isDigit)
这也是......
val l = sc.textFile("my_file_path")
val l_filtered = l.filter(x => x.take(1).Character.isDigit)
这也会引发错误。
这基本上是一个小错误,因为我不习惯Scala语法,所以我很难搞清楚它。任何帮助将不胜感激。
编辑:正如对此question的回答,我尝试编写该函数,但我无法在我的应用程序中的filter()函数中使用它。 为文件中的所有行应用此功能。
答案 0 :(得分:6)
在Scala索引语法中使用parens ()
而不是括号[]
。您的Python代码的确切翻译将是:
val l = sc.textFile("my_file_path")
val l_filtered = l.filter(_(0).isDigit)
第一个符号的更惯用的提取是使用head
方法:
val l = sc.textFile("my_file_path")
val l_filtered = l.filter(_.head.isDigit)
如果您的文件包含空行,这两种方法都会失败。
如果是这样,那么你可能想要这个:
val l = sc.textFile("my_file_path")
val l_filtered = l.filter(_.headOption.map(_.isDigit).getOrElse(false))
<强> UPD。强>
好奇的注明map(predicate).getOrElse(false)
上的Option
可以缩短为exists(predicate)
:
val l = sc.textFile("my_file_path")
val l_filtered = l.filter(_.headOption.exists(_.isDigit))
答案 1 :(得分:2)
您可以使用正则表达式:
scala> List("1hello","2world","good").filter(_.matches("^[0-9].*$"))
res0: List[String] = List(1hello, 2world)
或者你可以用较小的号码做这样的事。操作,因为此文件可能包含大量要过滤的行。
scala> List("1hello","world").filter(_.headOption.exists(_.isDigit))
res1: List[String] = List(1hello)
将List[String]
替换为您的案例中的l
行。