2013-04-15 29 views
7

我在循環中有多種場景,在遍歷項目進行處理時,我會'偷看'或'跳過'。Groovy'偷看'提前迭代器?

的一種情況是,我通過一個文件的行列舉,並有在指示下一行與當前行合併一行的末尾「延續」字符。如果我只是簡單循環,那麼我可以閱讀下一行,並且碰撞計數器/索引。

這是不是明顯的是與我的迭代器這樣的模式。我實際上想要在不退出關閉的情況下使用下一行。但我甚至不確定這是否可能。是否有使用閉包的迭代模式的良好設計模式,所以我不必訴諸於不太常規的循環?它可能是一個迭代器的形式,有一些堆棧用於處理推送/彈出項目嗎?

+3

我通常使用一個裝飾圍繞這樣的迭代器:https://gist.github.com/ataylor284/5389604 – ataylor

回答

1

我會做一個迭代,將負責相結合線。對於續行例子,迭代器可以把線從它的構造函數讀取該文件中,則有從線讀取其next方法,預讀時,發現一個連字符,以便延續字符先下一解決步入管道。所以你需要的任何狀態機都會包含在迭代器中。

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 
0

有趣的問題。

這裏的關鍵問題是,你需要通過反覆進行一些狀態。要做到這一點

的一種方法是使用一個外部變量(在這裏我使用字符串數組和List#each,而不是一個文件,並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 = '' 
    } 
} 

另一個方法是使用專門設計的攜帶狀態,儘管interations,像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."