Как перебрать список и удалить соответствующие элементы, чтобы создать новый список

Я новичок в Groovy Lists, и у меня есть список, как показано ниже:

Class File{
 String name 
 int type
 int revision
}

def fileList = [File1, File2, File3,....]

Я хочу fileList иметь последние файлы

  1. Не должно быть предметов одного типа
  2. Он должен иметь файлы с самой высокой ревизией, если два или более файлов имеют одинаковый тип, то в списке должен быть один файл с самой высокой ревизией.

Как мне это сделать в 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 для итерации ваших значений. Как я уже сказал, это наивный способ выполнить вашу задачу. Возможно, вы захотите найти хороший рекурсивный метод, который использует алгоритм сортировки.

Другие вопросы по тегам