7

処理のためにアイテムを繰り返し処理しながら、先に「ピーク」または「スキップ」するさまざまなシナリオがループ内にあります。

1 つのシナリオは、ファイルの行を列挙していて、行末に次の行を現在の行と結合することを示す「継続」文字があることです。それほど難しくない単純なループの場合は、次の行を読み込んで、カウンター/インデックスをバンプするだけです。

私のイテレータでこれを行うためのパターンは明らかではありません。クロージャーを終了せずに、次の行を効果的に消費したいと考えています。しかし、それが可能かどうかさえわかりません。クロージャーを使用したこの反復パターンに適した設計パターンはありますか? おそらく、処理のためにアイテムをプッシュ/ポップするためのスタックを備えたイテレータの形式ですか?

4

3 に答える 3

1

私はいつか似たようなものを実装しなければなりませんでした。各行にパイプで区切られたデータを含む大きなファイルがあり、データは次の行に続く可能性がありますが、次の行を「覗いた」かどうかしかわかりませんでした。ピークメソッドと組み合わせたスタックとして ArrayList の使用を終了しました。

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
于 2013-04-15T17:47:12.743 に答える
1

行の結合を担当するイテレータを作成します。行継続の例では、反復子はそのコンストラクターでファイルから読み取られた行を取得しnext、継続文字が見つかったときに先読みして、その行からそのメソッドを読み取り、継続文字が次のステップの前に解決されるようにすることができます。パイプラインで。したがって、必要なステート マシンはすべてイテレータ内に含まれます。

于 2013-04-15T16:00:20.883 に答える
0

興味深い質問です。

ここでの重要な問題は、繰り返しを通じて何らかの状態を保持する必要があることです。

これを行う 1 つの方法は、外部変数を使用することです (ここList#eachでは、ファイル and の代わりに文字列の配列 and を使用していますFile#eachLineが、類似している必要があります)。

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."
于 2013-04-15T18:10:21.220 に答える