Groovy list.sort первым, вторым, затем третьим элементом
У меня есть список списков groovy i.e.
list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
Я хотел бы отсортировать его по порядку первого элемента, затем второго, затем третьего.
Ожидаемое
assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]
Я начал с list = list.sort{ a,b -> a[0] <=> b[0] }
, но это только сортирует первый элемент. Как вы заканчиваете?
Спасибо
Ответы
Ответ 1
Вы должны иметь возможность выполнять итерацию по желаемой сортировке в обратном порядке:
list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
list = list.sort{ a,b -> a[2] <=> b[2] }
list = list.sort{ a,b -> a[1] <=> b[1] }
list = list.sort{ a,b -> a[0] <=> b[0] }
assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]
Каждый должен переопределить предыдущий, чтобы сохранить целостную сортировку.
Вы также можете связать их с помощью оператора Elvis, ?:
, который отложит до следующего сравнения, когда предыдущие равны (и <=>
возвращает 0
):
list.sort { a,b -> a[0] <=> b[0] ?: a[1] <=> b[1] ?: a[2] <=> b[2] }
Ответ 2
Если вы хотите сортировать массивы произвольной (хотя и однородной) длины, вы можете использовать это, и он сделает это за один проход:
def list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
list.sort { a, b ->
for (int i : (0..<a.size())) {
def comparison = (a[i] <=> b[i])
if (comparison) return comparison
}
return 0
}
assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]
Ответ 3
Вот еще один способ, использующий операторы Groovy Spaceship и Elvis :
def list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
list.sort { a, b ->
a[0] <=> b[0] ?: a[1] <=> b[1] ?: a[2] <=> b[2]
}
assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]
Источник: Groovier способ сортировки по нескольким полям в списке карт в Groovy
Ответ 4
Вы можете использовать библиотеку CollectionUtils от kobo-commons.
https://github.com/kobo/kobo-commons/wiki/sort-by-multiple-keys
import org.jggug.kobo.commons.lang.CollectionUtils
CollectionUtils.extendMetaClass()
list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
list = list.sort{ [ it[0], it[1], it[2] ]} // sort by multiple keys
assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]
list2 = [ [name:"a", age:13], [name:"a",age:15], [name:"b", age:13] ]
list2 = list2.sort{[it.name, it.age] } // sort by name and age
assert list2 == [[name:"a", age:13], [name:"a", age:15], [name:"b", age:13]]
Ответ 5
Выполнено Groovy, независимо от размера подсписков:
ll2.sort { l1, l2 ->
e1e2 = [l1, l2].transpose().find { e1, e2 ->
e1 != e2
}
e1e2 ? e1e2[0] <=> e1e2[1] : 0
}
Ответ 6
Вот что я придумал, не самый groovy способ, я полагаю..
list = list.sort{ a,b ->
if(a[0].compareTo(b[0]) == 0) {
if(a[1].compareTo(b[1]) == 0) {
return a[2].compareTo(b[2]);
} else {
return a[1].compareTo(b[1]);
}
} else {
return a[0].compareTo(b[0]);
}
}
Ответ 7
Вы можете сделать это в одной строке:
list.sort { String.format('%010d%010d%010d', it[0], it[1], it[2]) }