你如何在 Scala 中返回一个迭代器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2135462/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 01:52:17  来源:igfitidea点击:

How do you return an Iterator in Scala?

scalaiteratortraits

提问by Geo

What must I do in order to be able to return an Iterator from a method/class ? How would one add that trait to a class?

为了能够从方法/类返回迭代器,我必须做什么?如何将这种特征添加到类中?

回答by Mitch Blevins

You can extend Iterator, which will require that you implement the nextand hasNextmethods:

您可以扩展Iterator,这将要求您实现nexthasNext方法:

  class MyAnswer extends Iterator[Int] {
    def hasNext = true
    def next = 42
  }

But, you will get more flexibility if you extend Iterable, which requires you implement elements(or iteratorin 2.8):

但是,如果您扩展Iterable,您将获得更大的灵活性,这需要您实现elements(或iterator在 2.8 中):

  class MyAnswer extends Iterable[Int] {
    def iterator = new Iterator[Int] {
      def hasNext = true
      def next = 42
    }
  }

A common idiom seems to be to expose an iterator to some private collection, like this:

一个常见的习惯用法似乎是将迭代器暴露给某些私有集合,如下所示:

  class MyStooges extends Iterable[String] {
    private val stooges = List("Moe", "Larry", "Curly")
    def iterator = stooges.iterator
  }

回答by Jord?o

For a method, just yield:

对于方法,只需yield

def odd(from: Int, to: Int): List[Int] = 
  for (i <- List.range(from, to) if i % 2 == 1) yield i

回答by Ravi

These two answers had help from the posts below and thanks @Dima.

这两个答案从下面的帖子中得到了帮助,并感谢@Dima。

Lets assume you have a class linked list. And the requirement is to print all the elements in the list.

假设您有一个类链表。并且要求是打印列表中的所有元素。

trait LinkedList {
  def nodeValue: Int
  def tailList: LinkedList
}

class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList

object Nil extends LinkedList {
  def nodeValue = throw new IllegalAccessException("head of Nil")
  def tailList = throw new IllegalAccessException("tail of Nil")
}

val singleLinkedList = new Node(1,Nil)
val chainedLinkedList = new Node(2,singleLinkedList)
print(chainedLinkedList)
A$A44$A$A44$Node@7b7a2c78res0: Unit = ()

Now Lets implement iterator to this class.

现在让我们为这个类实现迭代器。

trait LinkedList extends Iterator[Int]{
  def nodeValue: Int
  def tailList: LinkedList
}

class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList {
  var ptr: LinkedList = this

  //The following two are mandatory for extending Iterator
  override def hasNext: Boolean = ptr match { case Nil => false; case _=> true}

  override def next(): Int = {
    val result = ptr.nodeValue
    ptr = ptr.tailList
    result
  }
}

object Nil extends LinkedList {
  def nodeValue = throw new IllegalAccessException("head of Nil")
  def tailList = throw new IllegalAccessException("tail of Nil")

  //The following two are mandatory for extending Iterator
  override def hasNext: Boolean = false
  override def next(): Int = throw new IllegalAccessException("next of Nil")
}

val singleLinkedList = new Node(1,Nil)
val chainedLinkedList = new Node(2,singleLinkedList)

//Printing this first Time
chainedLinkedList.foreach(println)
//Prints 2 1

//Printing second Time
chainedLinkedList.foreach(println)
//No output

In the iterator implementation, once ptr reached the end, it could did not advance back. Iterable implementation solves this.

在迭代器的实现中,一旦 ptr 到达终点,它就无法前进。迭代实现解决了这个问题。

trait LinkedList extends Iterable[Int]{
  val nodeValue: Int
  val tailList: LinkedList
  override def toString(): String = this.mkString(" -> ")
}

class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList {

  override def iterator: Iterator[Int] = Iterator
    .iterate(this: LinkedList)(_.tailList)
    .takeWhile(_ != Nil)
    .map(_.nodeValue)
}

object Nil extends LinkedList {
  lazy val nodeValue= throw new IllegalAccessException("head of Nil")
  lazy val tailList = throw new IllegalAccessException("tail of Nil")

  override def iterator: Iterator[Int] = Iterator.empty
}

val singleLinkedList = new Node(1,Nil)
val chainedLinkedList = new Node(2,singleLinkedList)

//Printing this first Time
chainedLinkedList.foreach(println)
Output 2 -> 1
chainedLinkedList.foreach(println)
Output 2 -> 1