2014-09-27 3 views
4

Список Destructuring (множественное присвоение) в Groovy может использоваться для привязки значений к переменным из списка. Например:Получение хвоста списка в нескольких присваиваниях в Groovy

def (first, second, third) = [1,2,3,4,5,6] 
assert third == 3 

Есть ли синтаксический способ достичь следующий:

def (first, second, <rest>) = [1,2,3,4,5,6] 
assert ​rest​ == [3,4,5,6] 

Если нет, то ближе/оптимистичный способа добиться того же результата, желательно в одном выражении?

ответ

3

Что вам нужно сделать, это преобразовать список из шести-трех элементов так, как вы описываете. То есть преобразовать [1,2,3,4,5,6] в [1,2,[3,4,5,6]]. Возможно, вы также захотите, чтобы это было настраиваемо для любого количества элементов.

Вот решение, в котором новый метод reduce добавляется List, который преобразует список в предложенном виде:

List.metaClass.reduce = { int size -> delegate[0..size-2] + [delegate[size-1..-1]] } 

def (first, second, rest) = [1,2,3,4,5,6].reduce(3) 
assert first == 1 
assert second == 2 
assert rest == [3,4,5,6] 

Edit: Прошлой ночью, когда спать, я думал об использовании with для достижения это как один лайнер. Это та же идея, что и выше, хотя и более загадочная (менее читаемая), поскольку логика встроена.

def (first, second, rest) = [1,2,3,4,5,6].with { it[0..1] + [it[2..-1]] } 
assert first == 1 
assert second == 2 
assert rest == [3,4,5,6] 
0

Я не думаю, что вы можете использовать несколько заданий для достижения этого. Вот один из вариантов:

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

def first = list[0] 
def second = list[1] 
def rest = list[2..-1] 
+0

Да, спасибо, что ответили. Я должен был быть более понятным (я обновил его сейчас). Я ищу один подход к выражению/деструктуризации, который может быть легко обобщен, так что def (a, b, c ... ) = [...] – kunal

+0

@kunal Я понимаю, чего вы хотите, но это просто невозможно для этого, поскольку синтаксис множественного присваивания будет присваивать только один элемент списка каждой переменной –

1

Ближайший я мог бы достичь это:

Вариант 1: Если поигрывая метакласса звучит как хорошая идея:

List.metaClass.destructure = { ...n-> 
    n.collect { delegate[it] } 
} 

def (a, b, rest) = [1,2,3,4].destructure(0, 1, 2..-1) 

Варианты 2. В противном случае старый добрый метод спасения:

def destructure (list,...n) { 
    n.collect { list[it] } 
} 

def (a, b, rest) = destructure([1,2,3,4], 0, 1, 2..-1) 

Вариант 3. Встроенное, но мало уродливое решение

def (a, b, rest) = [0, 1, 2..-1].collect { [1,2,3,4][it] } 

Все выше проходят критерии

assert rest​ == ​[3,4]​ 
0

Разновидность решений уже предложенных, которые используют with() + замыкание и collect() + замыкание. Это решение использует только замыкание с варгарами:

def (first, second, rest) = { ... a -> a[0..1] + [a[2..-1]]} (1,2,3,4,5,6) 

println first 
println second 
println rest