2012-04-30 29 views
6

有什麼辦法在下面的例子中刪除變量「i」,並且仍然可以訪問正在打印的項目索引?groovy - 是否有任何隱式變量可以訪問「每個」方法中的項目索引

def i = 0; 
"one two three".split().each { 
    println ("item [ ${i++} ] = ${it}"); 
} 

=============== EDIT ================

我發現,一種可能的解決方案是使用「eachWithIndex」方法:

"one two three".split().eachWithIndex {it, i 
    println ("item [ ${i} ] = ${it}"); 
} 

請讓我知道是否有其他解決方案。

回答

11

可以使用eachWithIndex()

"one two three four".split().eachWithIndex() { entry, index -> 
     println "${index} : ${entry}" } 

這將導致

0 : one 
1 : two 
2 : three 
3 : four 
0

不知道「其他的解決方案」,你正在尋找...唯一的其他東西你可以做什麼,我可以想想(用Groovy 1.8.6),就像這樣:

"one two three".split().with { words -> 
    [words,0..<words.size()].transpose().collect { word, index -> 
    word * index 
    } 
} 

正如你所看到的,這允許您也可以使用collect以及索引(因爲沒有collectWithIndex方法)。

+0

哇,這是牽強,murdochjohn這樣做是正確 – loteq

+0

@loteq這基本上就是我說...得到它的權利後,OP詢問_「其他解決方案」 _出於某種原因。另外,如果你想在'collect'中使用一個索引,'find',這是除了外部變量之外的唯一方法... –

+0

很酷的答案,但是使用'with'會阻礙IMO解決方案的可讀性。我在我的鏈接你的答案,這在'枚舉'方法= D – epidemian

0

另一種方法,如果你想使用集合的索引其他方法比each是定義enumerate方法返回對[index, element],模擬Python's enumerate

Iterable.metaClass.enumerate = { start = 0 -> 
    def index = start 
    delegate.collect { [index++, it] } 
} 

因此,例如:

assert 'un dos tres'.tokenize().enumerate() == [[0,'un'], [1,'dos'], [2,'tres']] 

(請注意,我使用tokenize代替split因爲前者返回一個可迭代,而後來的回報String[]

而且我們可以使用這個新的集合與each,因爲你想要的東西:

'one two three'.tokenize().enumerate().each { index, word -> 
    println "$index: $word" 
} 

或者我們可以與其他迭代方法使用它:d

def repetitions = 'one two three'.tokenize().enumerate(1).collect { n, word -> 
    ([word] * n).join(' ') 
} 
assert repetitions == ['one', 'two two', 'three three three'] 

:定義enumerate方法的另一種方法,以下是tim_yates'more functional approach

Iterable.metaClass.enumerate = { start = 0 -> 
    def end = start + delegate.size() - 1 
    [start..end, delegate].transpose() 
} 
相關問題