【问题标题】:Finding lines that start with a digit in Scala using filter() method使用 filter() 方法在 Scala 中查找以数字开头的行
【发布时间】:2015-09-25 18:32:16
【问题描述】:

我是一名 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() 函数中使用它。 将函数应用于文件中的所有行。

【问题讨论】:

标签: scala syntax apache-spark


【解决方案1】:

在 Scala 中,索引语法使用括号 () 而不是括号 []。你的 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。

正如好奇所指出的,Option 上的 map(predicate).getOrElse(false) 可以缩短为 exists(predicate)

val l = sc.textFile("my_file_path")
val l_filtered = l.filter(_.headOption.exists(_.isDigit))

【讨论】:

  • 感谢您的详细解答。激励我深入研究 Scala。
  • 如果你有一个空字符串,前两个例子是不安全的,第一个会给IndexOutOfBoundException,第二个会给NoSuchElementException,第三个是相当安全和好的,但是,而不是做地图headOption 然后做getOrElse 你可以简单地使用exists 方法。
  • 感谢您指出exists 方法,我更新了答案以包含它。前两个示例故意容易出错,因为原始代码也容易受到空字符串的影响。我想逐渐提高。此外,在大规模情况下(我猜这是应用 Spark 的地方),如果您确定输入数据格式,则可以通过省略冗余检查来提高速度。
【解决方案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 行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-11
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多