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、最初の 2 つは理にかなっています (Groovy の範囲には、Java の他の場所のように終了要素を省略するのではなく、終了要素が含まれます :-( )

行番号 3 は目的の出力です (最初と最後の要素のないリスト)。

出力 #4 が心配です: なぜ を得る[1, 0]のです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']

サイズ == 1 のコーナー ケースでは適切に動作します。

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

size == 0 の場合に例外をスローすることをお勧めしますが、動作はそれほど悪くはありません。

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

(3番目の例)を使用することもできlist[0..<list.size()-1]ます。空のリストを除いて同じように動作しArrayIndexOutOfBoundsExceptionますtake


もう1つの許容できる解決策は、list[0..-2](最後の例)を使用することです。これは、はるかにエレガントに見えると思いますが、サイズ== 1でArrayIndexOutOfBoundsException.


あなたの例では(最後の要素以外のすべての要素を含めたい場合は、開始インデックスとして 1 ではなく 0 を使用するつもりだったと仮定します):

lines[0..lines.size()-1]リストのメソッドは、負のインデックスを持つ範囲を、リストの 'th 要素にアクセスするのと同じように扱う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 はここで魔法の変換を行いません)。そして、それが size == 1 の場合に機能する理由list[0..<list.size()-1]です (範囲は空の範囲に評価されます) が、そうではありlist[0..-2]ません:)

于 2012-05-09T13:13:17.230 に答える
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 の場合です。

于 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 に答える