删除groovy列表中除最后一项之外的所有内容的最佳方法是什么?

时间:2013-02-13 08:07:03

标签: groovy

我一直试图找到一种巧妙的方法来删除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']

3 个答案:

答案 0 :(得分: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 )
}

答案 1 :(得分:0)

void removeAllButLastInPlace( List list ) {
    def index = 0
    list.reverse(true).retainAll({index++ == 0})
}

答案 2 :(得分:0)

我选择其中一个。我的标准是:a)按照要求修改清单(不返回新清单)和b)简洁。

然而,我已经使两个版本都返回对修改列表的引用,只是为了简化println示例。您可以将返回类型设为“无效”状态。如果愿意,删除最后的' 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([])