Groovy'偷看'使用迭代器?

时间:2013-04-15 15:25:13

标签: groovy iterator closures peek

我在循环中有各种场景,在迭代处理项目时我会“偷看”或“跳过”。

一种情况是我通过文件的行枚举,并且在行的末尾有一个“延续”字符,表示将下一行与当前行组合。如果我只是循环而不是太难,我可以阅读下一行,然后碰到我的计数器/索引。

使用我的迭代器执行此操作的模式并不明显。我实际上想要在不退出关闭的情况下使用下一行。但我甚至不确定这是否可行。使用闭包这个迭代模式是否有任何好的设计模式,所以我不必诉诸于一个不太常规的循环?它可能是一种迭代器形式,有一些堆栈用于推送/弹出项目进行处理吗?

3 个答案:

答案 0 :(得分:1)

我会创建一个负责组合线的迭代器。对于行继续示例,迭代器可以从其构造函数中的文件中读取行,然后从行读取next方法,在找到连续字符时向前读取,以便继续字符为在管道的下一步之前解决。因此,无论您需要什么状态机都将包含在迭代器中。

答案 1 :(得分:1)

我不得不在不久前实现类似的东西。我有一个大文件,每行都有管道分隔数据,数据可以在下一行继续,但我只能知道我是否“偷看”了下一行。我最后使用ArrayList作为堆栈并结合了peek方法:

def list = [1, 2, 3, 4, 5, 6, 7]

list.metaClass.peek = { delegate[-1] }

assert list.pop() == 7
assert list.pop() == 6
assert list.peek() == 5
assert list.peek() == 5
assert list.pop() == 5
assert list.pop() == 4
assert list.peek() == 3

答案 2 :(得分:0)

有趣的问题。

这里的关键问题是你需要通过迭代来携带一些状态。

这样做的一种方法可能是使用外部变量(这里我使用的是字符串数组List#each而不是文件和File#eachLine,但它们应该类似):< / p>

def lines = [
  "Single line.",
  "Long \\",
  "line \\",
  "continuation.",
  "Single line."
]

def processLine(line) { println "Processing \"$line\""}

def continuation = ''
lines.each { line ->
  line = continuation + line
  if (line.endsWith('\\')) {
    continuation = line.take(line.size() - 1)
  }
  else {
    processLine(line)
    continuation = ''
  }
}

另一种方法是使用专门设计的迭代器,以便通过Collection#inject之间的状态进行状态:

lines = lines.inject([]) { list, line ->
  if (list && list[-1].endsWith('\\'))
    list[-1] = list[-1][0..-2] + line
  else 
    list << line
  list
}

lines.each { processLine(it) }

在这种情况下,我们首先加入续行然后处理它们。

在这两种情况下,输出都是:

Processing "Single line."
Processing "Long line continuation."
Processing "Single line."