遍历类迭代器数据结构的惯用 Scala 方法

问题描述 投票:0回答:4

给定一个来自遗留库的类,它的行为类似于

Iterator
,这样您就可以使用
hasNext
next
遍历它的内容,但它没有实现
Iterator
接口:

class LegacyIterator[T](iterable: Iterable[T]) {
  val iterator: Iterator[T] = iterable.iterator
  def hasNext: Boolean = iterator.hasNext
  def next(): T = iterator.next()
}

val lagIter: LegacyIterator[Int] = new LegacyIterator(List(1, 2, 3))

您对遍历此类数据结构的最优雅方式有何看法 - 最好是在函数范围内?我想出了两个版本:

一个使用

@tailrec

@tailrec
def lagIterList(accu: List[Int]): List[Int] =
  if (lagIter.hasNext) lagIterList(lagIter.next() :: accu) else accu

val res = lagIterList(Nil).reverse

还有一个使用

LazyList

def ll: LazyList[Int] = if(lagIter.hasNext) lagIter.next() #:: ll else LazyList.empty
val res = ll.toList

你认为什么更符合 Scala 的习惯?

tailrec
版本在较大的数据结构上可能稍微快一些,但
LazyList
版本更好地利用集合库。

或任何其他想法?

scala iterator tail-recursion lazylist
4个回答
2
投票

我会考虑一个扩展 Iterator[T] 的隐式包装类:

implicit class LegacyIteratorWrapper[T](private val underlying: LegacyIterator[T]) extends Iterator[T] {
  override def hasNext: Boolean = underlying.hasNext
  override def next(): T = underlying.next()
}

val lagIter: LegacyIterator[Int] = new LegacyIterator(List(1, 2, 3))

// traversal
for (elem <- lagIter) println(elem)

// conversion to list
val lagIterList = lagIter.toList

1
投票

只需将其转换为普通迭代器即可:

val normalIterator = Iterator.continually(legacyIterator)
  .takeWhile(_.hasNext)
  .map(_.next)

然后您可以使用任何常规的 Scala 工具来遍历/转换它,例如:

 val list = normalIterator.toList


1
投票

嗯,这取决于你所说的“遍历它”是什么意思。 如果你只是想用它创造一个

List
,我会用
unfold

def toList[T](iter: LegacyIterator[T]): List[T] =
  List.unfold(()) { _ =>
    Option.when(iter.hasNext()) {
      iter.next() -> ()
    }
  }

0
投票

foreach 方法采用一个应用于集合中每个元素的函数,允许您对每个元素执行操作而无需显式迭代:

val it = Iterator(1, 2, 3, 4, 5)

it.foreach { element =>
  println(s"The current element is: $element")
}

在 Scala 中使用

foreach
优于 explicit iteration 因为它更简洁并且通常更有效。
foreach
方法也可以用在函数式风格中,允许您在一个表达式中将多个操作链接在一起:

val result = Iterator(1, 2, 3, 4, 5)
  .filter(_ % 2 == 0)
  .map(_ * 2)
  .toList
© www.soinside.com 2019 - 2024. All rights reserved.