【问题标题】:Sliding iterator skipping elements?滑动迭代器跳过元素?
【发布时间】:2015-09-25 09:54:39
【问题描述】:

我有一个函数定义如下(为了论证而简化):

def sendRecords(records: Iterator[Map[String, String]]) = {
    records.sliding(10,10).foreach { case recordList => println(recordList) } 
} 

当我调用这个函数时,我可以从 println(并且知道预期的答案是什么)看到 recordList 确实是一批 10,但不知何故,“记录”中的某些项目似乎被跳过了。在这种情况下,输出缺少第 1 个、第 12 个、第 13 个、第 24 个、第 25 个……(即似乎有一些奇怪的规律性)。请注意,每个单个元素都是 string-> string 的映射(并且内容是机密的),但为了说明起见,输出的简化形式可以是

[1,2,3,4,5,6,7,8,9,10],[13,14,15,16,17,18,19,20,21,22],[....]

对于批处理案例和

[0,1,2,3,4,5,6,7,8,9], [10,11,12,13,14,15,16,17,18,19],[....]

对于“toList.iterator”(见下文)的情况,这是可以预料的。在这些输出中,我已将地图替换为标识它们的索引。

我完全不知道为什么会发生这种情况。请注意,“记录”是我自己实现的迭代器(即使用 hasNext 和 next)——我怀疑这很重要。但是,实现相当复杂。我在底部添加了主要部分。

不过,有一些迹象表明它是正确的

records.toList.iterator.sliding(10,10).foreach { case recordList => println(recordList) } 

工作正常,那

records.foreach { println } 

看起来也符合预期(即它单独打印每个元素,并且列表是完整的)。

有人知道这里有什么吗 - 或者建议我可以尝试一些其他的事情吗?任何帮助将非常感激。我正在使用 scala 2.10.5。

(请注意,虽然 toList.iterator hack 有效,但在这里它是不可接受的,因为这会在内存中构建整个列表,这在生产中会太大)。

谢谢! -乔里斯。

迭代器还没有完全整理好,所以请原谅一些潜在的狡猾代码(这可能导致了这个问题),但它的想法是遍历一个逗号分隔的文件(即“行”输入)有一个相当复杂的标题定义(因此是状态方法)。我不能展示解码器,因为那是保密的,但我希望这应该足够了。也许我的 hasNext/next 有缺陷。

class DecodingIterator(lines: Iterator[String]) extends Iterator[Map[String, String]] {
  val decoder = new StatefulDecoder()
  var cachedRecord = Map[String,String]()

  def hasNext: Boolean = {
    if (!lines.hasNext || decoder.inState(decoder.Finished()))
        false
    else {
      while(!decoder.inState(decoder.Data())) {
        decoder.processLine(lines.next)
      }
      decoder.processLine(lines.next)
      cachedRecord = decoder.lastRecord
      !decoder.inState(decoder.Finished())
    }
  }

  def next = cachedRecord
}

【问题讨论】:

  • 你能提供你的迭代器实现、预期输出和实际输出吗?
  • 您确实应该添加 records 迭代器的代码。不相关,可以将sliding(10, 10)替换为grouped(10)
  • 是的,我已经添加了迭代器的主要部分。它依赖于我无法展示的“StatefulDecoder”。但现在应该有希望充分说明 hasNext/next 逻辑。
  • 我想知道“it.hasNext”是否在“it.next()”之前被多次调用。从我的实现中可以看出,重复调用 it.hasNext() 并不是幂等的。
  • @JorisPeeters 这确实是正在发生的事情,在每个切片 hasNext 被调用两次之前,所以你会丢失 1 个元素。

标签: scala


【解决方案1】:

正如问题的 cmets 中所讨论的,问题出在迭代器的实现上,它在“hasNext”上的行为并不相同(并且“滑动”导致它连续调用不止一次) .

修复后,一切正常。 谢谢大家的帮助。

【讨论】:

    猜你喜欢
    • 2023-01-11
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多