首页 > 解决方案 > 如何概括 'Seq[String] => Seq[Int]' 和 'Iterator[String] => Iterator[Int]' 的实现以进行文件处理?

问题描述

假设我有一个函数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]. 这是正确的吗 ?避免重复代码的最佳方法是什么?

标签: scalafileioiterator

解决方案


如果你有一个任意函数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"))

推荐阅读