18

以下 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]for 1..-1

同样[1, 2, 3, 4, 5]对于范围1..<-2似乎是错误的。

为什么会这样?

4

3 回答 3

19

在我看来,获取除最后一个元素之外的所有元素的最佳方法是使用以下take方法:

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

它在 size == 1 的极端情况下表现正常:

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

虽然我更希望它在 case size == 0 的情况下抛出异常,但行为并没有那么糟糕:

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

您也可以使用list[0..<list.size()-1](您的第三个示例),除了空列表外,它的行为相同,在这种情况下它会抛出一个ArrayIndexOutOfBoundsException,但我认为它不像take对应的那样可读。


另一个可接受的解决方案是使用list[0..-2](你的最后一个例子),我认为它看起来更优雅,但不幸的是当 size == 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]当 size == 1 (范围评估为空范围)时有效,而list[0..-2]没有 :)

于 2012-05-09T13:13:17.230 回答
4

自从 Epideman 写下他的答案以来,这可能已经改变了,但是你可以得到整个列表而没有最后一个元素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) == []

这是 groovy 2.2.1。

于 2014-07-09T03:17:02.463 回答
3

从 Groovy 2.4 开始,您可以使用init()方法:

lines = ['0','1','2','3','4','5']
assert lines.init() == ['0','1','2','3','4']
于 2017-03-30T13:44:12.037 回答