2012-05-09 39 views
12

以下Groovy代碼如何從列表中獲取沒有最後一個元素的所有元素?

lines = ['0','1','2','3','4','5'] 
    println lines[1..lines.size()-1] 
    println lines[1..-1] 
    println lines[1..<lines.size()-1] 
    println lines[1..<-1] 
    println lines[1..<-2] 
    println lines[1..-2] 

產生以下輸出:

[1, 2, 3, 4, 5] 
[1, 2, 3, 4, 5] 
[1, 2, 3, 4] 
[1, 0] 
[1, 2, 3, 4, 5] 
[1, 2, 3, 4] 

由於-1是該列表中的最後一個元素的索引,前兩個有意義(在Groovy範圍包括端部元件而不是像Java中的其他地方一樣省略它:-()

第3行是所需的輸出(沒有第一個和最後一個元素的列表)

我很擔心輸出#4:爲什麼我得到[1, 0]1..-1

另外[1, 2, 3, 4, 5]範圍1..<-2似乎是錯誤的。

爲什麼會發生這種情況?

+1

不應該的範圍是從0而不是1開始,如果您要包括所有要素,但最後? (在你的例子中,你總是排除第一個元素) – epidemian

+0

在我的情況下,我也不想要第一個元素,但這不是我的問題的主要觀點。 –

回答

15

採取的所有元素,但最後一個最好的方式,在我看來,是使用take方法:

def list = ['a', 'b', 'c'] 
assert list.take(list.size() - 1) == ['a', 'b'] 

它正常的行爲在角落情況下大小== 1:

def list = ['one'] 
assert list.take(list.size() - 1) == [] 

雖然我寧願它扔在外殼尺寸== 0個例外,但行爲並不壞:

def list = [] 
assert list.take(list.size() - 1) == [] 

你也可以使用list[0..<list.size()-1](你的第三個例子),除了空列表之外,它的行爲是一樣的,在這種情況下,它會拋出一個ArrayIndexOutOfBoundsException,但我認爲它不如take對應的那麼可讀。


另一種可接受的解決方案是使用list[0..-2](你的最後一個例子),我認爲這看起來更優雅,但不幸的是打破時尺寸== 1與ArrayIndexOutOfBoundsException


在你的例子(我假設你的意思是使用0作爲起始索引,而不是1,如果你想包括所有要素,但最後一個):

lines[0..lines.size()-1]相當於lines[0..-1]因爲getAt(Range)列表方法將以與getAt(Integer)相同的方式處理具有負索引的範圍,即訪問列表的第(list.size() + negativeIndex)個元素。因此list[0..-1]與「從第一個元素到最後一個」的含義相同,與複製列表相同; list[-1..0]與「從上到下」是一樣的,它相當於list.reverse() :)

其他非包含範圍示例的問題是非包含範圍在列表訪問之前正在評估,它們評估到不正確的包容性範圍。例如,0..<-2評估爲0..-1,這就是它返回所有元素的原因。 0..<-1評估爲0..0,它只返回第一個元素。

請注意,空白範圍是一種特殊情況。它表示爲0..<0,它沒有包含的等價物(所以Groovy在這裏不會做任何魔術轉換)。這就是爲什麼list[0..<list.size()-1]工作時,大小== 1(範圍評估爲空的範圍),而list[0..-2]不:)

+1

+1 FWIW,_'magic conversion'_ [發生在這裏](https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethodsSupport.java #L36)和返回的'RangeInfo'對象[使用](https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java# L4634)調用[標準Java'List.subList'](http://docs.oracle.com/javase/6/docs/api/java/util/List.html#subList%28int,%20int%29)方法 –

3

也許這已經改變自從流行病寫他的答案,但你可以得到整個名單沒有最後元素與0..<-1

assert ["foo"][0..<-1] == [] 
assert ["foo", "bar"][0..<-1] == ["foo"] 
assert ["foo", "bar", "baz"][0..<-1] == ["foo", "bar"] 


// blows up if empty, here take is better 
assert [][0..<-1] == [] // BOOM 

// if you want null safe, use take 
assert [].take(-1) == [] 

這是與常規2.2.1。

2

由於Groovy的2.4可以使用init()方法:

lines = ['0','1','2','3','4','5'] 
assert lines.init() == ['0','1','2','3','4'] 
相關問題