【问题标题】:How to generalise implementations of 'Seq[String] => Seq[Int]' and 'Iterator[String] => Iterator[Int]' for file processing?如何概括 'Seq[String] => Seq[Int]' 和 'Iterator[String] => Iterator[Int]' 的实现以进行文件处理?
【发布时间】:2020-03-26 22:08:12
【问题描述】:

假设我有一个函数Seq[String] => Seq[Int],例如def len(as: Seq[String]): Int = as.map(_.length)。现在我想将此功能应用于文本文件,例如将所有文件行转换为数字。

我以scala.io.Source.fromFile("/tmp/xxx.txt").getLines 读取了一个文本文件,它返回一个迭代器。
我可以使用toListto(LazyList) 将迭代器“转换”为Seq,然后我将整个 文件读入内存。

所以我需要编写另一个函数Iterator[String] => Iterator[Int],它实际上是Seq[String] => Seq[Int]复制 版本。这是正确的吗 ?避免重复代码的最佳方法是什么?

【问题讨论】:

    标签: scala file io iterator


    【解决方案1】:

    如果你有一个任意函数Seq[String] => Seq[Int],那么

    我使用 toList 或 to(LazyList) 将迭代器“转换”为 Seq,但在这两种情况下,我都会读取内存中的整个文件。

    是你能做的最好的,因为函数可以从Seq[String]的末尾开始,或者它的长度等。

    而且 Scala 不允许您查看函数的“内部”并找出“它是 map(something),我可以对迭代器执行相同的 map”(宏有一些注意事项,但在这里并不是很有用)。

    所以我需要再写一个函数Iterator[String] => Iterator[Int],实际上是Seq[String] => Seq[Int]的一个复制版本。这是正确的吗 ?避免重复代码的最佳方法是什么?

    如果您控制函数的定义,则可以使用更高种类的类型来定义适用于两种情况的函数。例如。在 Scala 2.13 中

    def len[C[A] <: IterableOnceOps[A, C, C[A]]](as: C[String]): C[Int] = as.map(_.length)
    
    val x: Seq[Int] = len(Seq("a", "b"))      
    val y: Iterator[Int] = len(Iterator("a", "b"))
    

    【讨论】:

      猜你喜欢
      • 2020-08-12
      • 1970-01-01
      • 1970-01-01
      • 2018-06-29
      • 1970-01-01
      • 2022-08-23
      • 2017-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多