Roy Truelove Roy Truelove - 3 months ago 40
Groovy Question

Groovy list shift and unshift

Is there really no built-in way to 'shift' and 'unshift' with lists in groovy? (something that ruby, javascript have) For instance:

def list = [1,2,3,4,5]
firstElement = list.shift
println firstElement // 1
println list // [2,3,4,5]

list.unshift 1
println list // [1,2,3,4,5]


If no built in way, are there conventional alternatives?

Answer

There's no built in shift and unshift... Here are some options:

You could use a queue:

def queue = [ 1, 2, 3, 4, 5 ] as Queue

def firstElement = queue.poll()

assert firstElement == 1
assert queue == [ 2, 3, 4, 5 ]

But adding back in with offer adds to the wrong end, so use offerFirst:

queue.offerFirst( 1 )
assert queue == [ 1, 2, 3, 4, 5 ]

Or you could use a Stack, but you'd need to reverse your list to get 1 as the first element off of it.

def stack = [ 1, 2, 3, 4, 5 ].reverse() as Stack

def firstElement = stack.pop()

assert firstElement == 1
assert stack == [ 5, 4, 3, 2 ]

stack.push( 1 )
assert stack == [ 5, 4, 3, 2, 1 ]

Or, you could go the long way round:

def list = [ 1, 2, 3, 4, 5 ]

(firstElement, list) = [ list.head(), list.tail() ]

assert firstElement == 1
assert list == [ 2, 3, 4, 5 ]

list.add( 0, 1 )
assert list == [ 1, 2, 3, 4, 5 ]

Or you could add shift and unshift to the metaClass of List:

List.metaClass.shift = {
    delegate.remove( 0 )
}
List.metaClass.unshift = { val ->
    delegate.add( 0, val )
    delegate
}

def list = [ 1, 2, 3, 4, 5 ]
def firstElement = list.shift()
assert firstElement == 1
assert list == [ 2, 3, 4, 5 ]

list.unshift( 1 )
assert list == [ 1, 2, 3, 4, 5 ]