Как перебрать список и удалить соответствующие элементы, чтобы создать новый список
Я новичок в Groovy Lists, и у меня есть список, как показано ниже:
Class File{
String name
int type
int revision
}
def fileList = [File1, File2, File3,....]
Я хочу fileList
иметь последние файлы
- Не должно быть предметов одного типа
- Он должен иметь файлы с самой высокой ревизией, если два или более файлов имеют одинаковый тип, то в списке должен быть один файл с самой высокой ревизией.
Как мне это сделать в Groovy?
3 ответа
Ты можешь использовать Collection#groupBy
создать карту с записью для каждого уникального имени файла. Вы можете использовать Map#collect
перебрать содержимое этой карты и создать список, который вы хотите. Значения карты будут списком экземпляров File
, так Collection#max
позволит вам найти ту, которая имеет наибольший номер ревизии.
class File {
String name
int type
int revision
String toString() { "File(name: $name; type: $type; revision: $revision)" }
}
final files = [
new File(name: 'foo', type: 0, revision: 0),
new File(name: 'bar', type: 0, revision: 0),
new File(name: 'bar', type: 0, revision: 1),
new File(name: 'baz', type: 0, revision: 0),
new File(name: 'baz', type: 0, revision: 1),
new File(name: 'baz', type: 1, revision: 1),
]
final result = files.groupBy { it.name }
. collect { name, revisions -> revisions.max { it.revision } }
Я не уверен, что вы имели в виду, когда говорили, что в списке не должно быть предметов одного типа. Вы заметите, что если есть два случая File
с тем же именем и номером ревизии, но разными типами, это решение выбирает один произвольно.
Это наивный пример использования кода Джастина Пайпера. Прочитайте те API, которые я опубликовал, а также List JDK. Вы определенно сможете сделать более эффективный метод. Этот код должен дать вам хорошее представление о том, как работает Groovy и что можно сделать с замыканиями.
class File {
String name
int type
int revision
String toString() { "File(name: $name; type: $type; revision: $revision)" }
}
def files = [
new File(name: 'First Type2', type: 2, revision: 0),
new File(name: 'First Type0', type: 0, revision: 1),
new File(name: 'First Type1', type: 1, revision: 1),
new File(name: 'Second Type0', type: 0, revision: 0),
new File(name: 'Second Type1', type: 2, revision: 1),
new File(name: 'Second Type2', type: 1, revision: 1),
]
//This will hold the final set of files according to the logic in the next each()
def selectedFiles = [:]
files.each { file ->
//Overwrite the value associated with the key, which is the type depending on the logic - we only keep 1 of each type
if(selectedFiles[file.type]){
if(selectedFiles[file.type].revision < file.revision){
selectedFiles[file.type] = file
}
}
else{
//This type never existed, so just write the file as the value
selectedFiles[file.type] = file
}
}
selectedFiles.each { type, file ->
println(file)
}
Я бы предложил прочитать http://groovy.codehaus.org/groovy-jdk/java/util/Collection.html и http://groovy.codehaus.org/Collections
Очень наивный способ сделать это будет использовать метод сбора следующим образом
fileList.collect { file ->
//your condition
}.unique { file ->
//code that determines uniqueness
}
Вы можете написать как часть вашего условия в закрытии сбора, чтобы вернуть false для дубликатов, тогда вам не нужно было бы вызывать unique ()
[РЕДАКТИРОВАТЬ] Думая о проблеме, с которой вы столкнулись, вы на самом деле не хотели бы использовать вышеуказанные методы. Используйте метод each для итерации ваших значений. Как я уже сказал, это наивный способ выполнить вашу задачу. Возможно, вы захотите найти хороший рекурсивный метод, который использует алгоритм сортировки.