如何迭代列表并删除匹配的项目以创建新列表

时间:2012-08-31 12:32:07

标签: groovy groovy-2

我是groovy Lists的新手,我的列表如下所示:

Class File{
 String name 
 int type
 int revision
}

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

我希望fileList拥有最新的文件

  1. 不应该有相同类型的物品
  2. 它应具有最高版本文件,如果两个或多个文件具有相同类型,则列表必须具有最高版本的单个文件。
  3. 如何在Groovy中执行此操作?

3 个答案:

答案 0 :(得分: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有两个具有相同名称和修订号但类型不同的实例,则此解决方案会随意选择一个。

答案 1 :(得分:0)

我建议阅读 http://groovy.codehaus.org/groovy-jdk/java/util/Collection.htmlhttp://groovy.codehaus.org/Collections

一种非常天真的方法是使用collect方法,如下所示

fileList.collect { file ->
  //your condition
}.unique { file ->
  //code that determines uniqueness
}

您可以在collect闭包中写入条件的一部分,以便为重复项目返回false,那么您就不必调用unique()

[编辑]考虑到您遇到的问题,您实际上不希望使用上述方法。使用每种方法迭代您的值。正如我所说的,这是完成任务的一种天真的方式,你可能想要研究一种好的递归方法,它可以背负排序算法。

答案 2 :(得分:0)

这是使用Justin Piper的一些代码的一个天真的例子。仔细阅读我发布的那些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)
}