如何从列表中获取没有最后一个元素的所有元素?

时间:2012-05-09 12:33:37

标签: groovy

以下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中的范围包括end元素,而不是像Java中的其他地方一样省略它:-()

第3行是所需的输出(没有第一个和最后一个元素的列表)。

我担心输出#4:为什么我[1, 0]获得1..-1

范围[1, 2, 3, 4, 5]的{​​{1}}似乎也是错误的。

为什么会这样?

3 个答案:

答案 0 :(得分:17)

在我看来,采用所有元素但最后一个元素的最佳方法是使用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)的方式相同,即访问{{1}列表的元素。因此(list.size() + negativeIndex)与“从第一个元素到最后一个元素”的说法相同,它与复制列表相同;和list[0..-1]与“从最后到第一个”相同,它相当于list[-1..0]:)

其他非包含范围示例的问题是在列表访问之前正在评估非包含范围,并且它们评估为不正确的包含范围。例如,list.reverse()评估为0..<-2,这就是它返回所有元素的原因。 0..-1评估为0..<-1,它只返回第一个元素。

请注意,空范围是一种特殊情况。它表示为0..0,并且没有包含等价物(因此Groovy不会在此处进行任何魔术转换)。这就是为什么0..<0在size == 1(范围评估为空范围)时工作的原因,而list[0..<list.size()-1]没有:)

答案 1 :(得分:4)

自从流行者写下他的答案以来,这可能已经发生了变化,但你可以在没有最后一个元素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。

答案 2 :(得分:2)

从Groovy 2.4开始,您可以使用enter image description here方法:

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