【问题标题】:How to modify Iterator on the fly without mutable variables?如何在没有可变变量的情况下即时修改迭代器?
【发布时间】:2017-11-21 22:53:55
【问题描述】:

我有一些迭代器

val i: Iterator[String] = //..

它正在迭代大量的Strings。所以不可能将所有内容加载到内存中。我需要生成Iterator[String],它在源迭代器的每个元素之间插入分隔符(比如"separator")。例子

["1", "2", "3"] --> ["1", "separator", "2", "separator", "3"]
["1", "2"] --> ["1", "separator", "2"]
["1"] --> ["1"]
[] --> ["1"]

我找到了一个可变变量的解决方案:

class SeparatedIterator(i: Iterator[String]) extends Iterator[String] {
    private var pointToElement = false

    override def hasNext: Boolean =
      if (pointToElement && i.hasNext) true
      else i.hasNext

    override def next(): String =
      if(pointToElement && i.hasNext) {
        pointToElement = false
        "separator"
      }
      else if (i.hasNext) {
        pointToElement = true
        i.next()
      } else throw new NoSuchElementException
  }

有没有一种功能性的方法可以做到这一点?没有可变变量?

【问题讨论】:

    标签: scala iterator


    【解决方案1】:

    您可以在输入迭代器上使用flatMap 将每个元素替换为元素,然后是分隔符。为了避免最后的分隔符,你可以添加一个if来检查迭代器中是否还有元素:

    def separatedIterator(iter: Iterator[String]): Iterator[String] = {
        iter.flatMap { x =>
            if (iter.hasNext) Iterator(x, "separator")
            else Iterator(x)
        }
    }
    

    或者,按照 Karl Bielefeldt 的建议,您可以先放置分隔符,然后使用 drop 来摆脱它,而不是使用 if

    def separatedIterator(iter: Iterator[String]): Iterator[String] = {
        iter.flatMap { x => Iterator("separator", x) }.drop(1)
    }
    

    【讨论】:

    • 如果先放分隔符,可以iter flatMap {"separator" :: _ :: Nil} drop 1去掉第一个分隔符。
    • @St.Antario, drop 之所以有效,是因为在 Scala 中它的设计是安全的。根据文档,它“将此迭代器推进到第一个''n''元素或迭代器的长度,以较小者为准
    猜你喜欢
    • 1970-01-01
    • 2021-04-11
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-15
    • 2013-02-28
    相关资源
    最近更新 更多