【问题标题】:consume items from a scala Iterator使用 Scala 迭代器中的项目
【发布时间】:2011-11-28 23:56:22
【问题描述】:

我对特征 Iterator 中方法 take 的行为感到困惑。它似乎不消耗物品。这是一个例子:

scala> Iterator(1,2,3)
res0: Iterator[Int] = non-empty iterator

scala> res0 take 2 toArray
res1: Array[Int] = Array(1, 2)

scala> res0.next
res2: Int = 1

显然第 2 步消耗了两个项目,但在第 3 步中,Iterator 仍然是第一个项目。查看实现,我看不到任何类型的复制或缓冲,只有一个新的 Iterator 委托给底层的。怎么可能?我怎样才能真正消费 n 个项目?

【问题讨论】:

    标签: scala iterator scala-collections


    【解决方案1】:

    有问题的迭代器在IndexedSeqLike#Elements (source) 中定义。 ticket was recently filed 关于 take 在不同迭代器实现中的不一致行为。

    要真正消耗N个物品,调用Iterator#nextN次。

    您可能要考虑使用Stream,它是惰性的(如Iterator),但也是不可变的(不像Iterator)。

    scala> val s = Stream(1, 2, 3)
    s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
    
    scala> s.take(2).toList
    res43: List[Int] = List(1, 2)
    
    scala> s.take(2).toList
    res44: List[Int] = List(1, 2)
    
    scala> s.drop(2).toList
    res45: List[Int] = List(3)
    
    scala> {val (s1, s2) = s.splitAt(2); (s1.toList, s2.toList)}
    res46: (List[Int], List[Int]) = (List(1, 2),List(3))
    

    【讨论】:

    • 谢谢retronym,我明白了。让我放弃Stream 的原因是缺少诸如“当前项指针”之类的东西(顺便说一句,可能是由于 Java 的影响,人们可能会在所谓的东西中期望这种东西)。现在我看到我可以得到一个带有drop 序列的“当前指针”并查看head。我会再试一次。
    【解决方案2】:

    谢谢各位。

    这是我从Iterator 消费一堆物品的解决方案:

      implicit def consumable(i: Iterator[_]) = new {
        def next(n: Int) = {
          (for (_ <- 1 to n) yield i.next()).iterator
        }
        def skip(n: Int) {
          (1 to n).foreach(_ => i.next())
        }
      }
    

    欢迎任何 cmets。

    【讨论】:

    • 为了和返回类型一致,定义应该是:implicit def consumable[T](i: Iterator[T]) 否则返回Iterator[Any]
    【解决方案3】:

    你想消费这些物品,drop 他们。请注意,在 Iterator 上调用的大多数方法都会使 Iterator 无法进一步使用——在行为未定义且可能会更改的意义上说是无用的。

    【讨论】:

    • drop 实际上与take 存在相同的不一致。 {val i = Iterator(1, 2, 3); i.drop(1); i.next} 返回 1,而不是 2
    • @retronym 一旦你在i 上调用了dropi 就不能再可靠地使用了。相反,您必须使用 drop 返回的内容。
    • 好点。 {val i = Iterator(1, 2, 3); i.drop(1).next} 给出 2。除 next()hasNext() 之外的所有内容(可能)都会使原始迭代器无效;尽管这些方法可能会返回一个 new 有效的迭代器。我期待您的文档贡献来澄清这一点。
    猜你喜欢
    • 2013-10-05
    • 1970-01-01
    • 2021-04-21
    • 2012-09-20
    • 2013-06-15
    • 2010-12-16
    • 2012-03-08
    • 2013-04-27
    • 1970-01-01
    相关资源
    最近更新 更多