-1

我一直在尝试找到一种巧妙的方法来从 groovy 列表中删除除最后一个元素之外的所有元素,但我尝试过的所有事情似乎都有些过于复杂。有没有更简洁的方法?

失败:java.util.ConcurrentModificationException

void removeAllButLastInPlace(list) {
    if(list.size() > 1) {
        def remove = list[0..-2]
        remove.each { list.remove(it) }
    }
}

失败:java.lang.CloneNotSupportedException: java.util.ArrayList$SubList

void removeAllButLastInPlace(list) {
    if(list.size() > 1) {
        def remove = list[0..-2].clone()
        remove.each { list.remove(it) }
    }
}

工作,但列表构造似乎没有必要

void removeAllButLastInPlace(list) {
    if(list.size() > 1) {
        def remove = [] + list[0..-2]
        remove.each { list.remove(it) }
    }
}

工作,但似乎有点神秘

void removeAllButLastInPlace(list) {
    (list.size() - 1).times { list.remove(0) }
}

工作,也许最“正确”

void removeAllButLastInPlace(list) {
    list.retainAll { list.lastIndexOf(it) == list.size() - 1 }
}

代码应满足以下测试:

list = []
removeAllButLastInPlace(list)
assert list == []

list = ['a']
removeAllButLastInPlace(list)
assert list == ['a']

list = ['a', 'b']
removeAllButLastInPlace(list)
assert list == ['b']

list = ['a', 'b', 'c']
removeAllButLastInPlace(list)
assert list == ['c']
4

3 回答 3

2

与其改变现有列表,不如返回一个新列表?

然后你可以简单地做:

List removeAllButLast( List list ) {
  list ? [list[-1]] : []
}

或者:

List removeAllButLastInPlace( List list ) {
  list.drop( list.size() - 1 )
}

编辑:

你也可以使用一个循环(如果你必须有一个变异方法)

void removeAllButLastInPlace( List list ) {
   while( list.size() > 1 ) list.remove( 0 )
}
于 2013-02-13T09:05:56.673 回答
0
void removeAllButLastInPlace( List list ) {
    def index = 0
    list.reverse(true).retainAll({index++ == 0})
}
于 2013-02-13T09:14:32.943 回答
0

我会去其中之一。我的标准是 a)按照您的要求修改列表(不返回新列表)和 b)简洁。

然而,我让两个版本都返回对修改列表的引用,只是为了简化println示例。如果愿意,您可以将返回类型设置为“void”,并从每个中删除最后一个“xs”行。

def xs1 = [1, 2, 3, 4, 5]
def xs2 = [9]
def xs3 = []

def keepOnlyLast1(xs) {
    while(xs.size() > 1) xs.remove(0)
    xs
}

def keepOnlyLast2(xs) {
    xs[0 ..< xs.size()-1] = []
    xs
}

println "Version 1"
println keepOnlyLast1([] + xs1)
println keepOnlyLast1([] + xs2)
println keepOnlyLast1([] + xs3)

println "Version 2"
println keepOnlyLast2([] + xs1)
println keepOnlyLast2([] + xs2)
println keepOnlyLast2([] + xs3)

/* Sanity check that these methods *really* modify the list. */
println "Sanity Check"
keepOnlyLast1(xs1)
println xs1
keepOnlyLast2(xs2)
println xs2

旁白:如果可能的话,我也会选择一种更实用的样式(即返回一个新列表而不是修改现有列表),但那不是您所要求的。无论如何,这是一个例子:

def lastAsList(xs) {
    xs.isEmpty() ? [] : [xs[-1]]
}
println lastAsList([1, 2, 3])
println lastAsList([])
于 2015-06-09T10:39:27.250 回答