我是 groovy 列表的新手,我的列表如下所示:
Class File{
String name
int type
int revision
}
def fileList = [File1, File2, File3,....]
我希望fileList
拥有最新的文件
- 它不应该有相同类型的项目
- 它应该具有最高版本的文件意味着,如果两个或多个文件具有相同的类型,则列表必须具有最高版本的单个文件。
我如何在 Groovy 中做到这一点?
您可以使用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
具有相同名称和修订号但类型不同的实例,则此解决方案会任意选择一个。
我建议阅读 http://groovy.codehaus.org/groovy-jdk/java/util/Collection.html 和 http://groovy.codehaus.org/Collections
这样做的一个非常天真的方法是使用 collect 方法如下
fileList.collect { file ->
//your condition
}.unique { file ->
//code that determines uniqueness
}
您可以在 collect 闭包中将其作为条件的一部分编写为重复项返回 false ,然后您就不必调用 unique()
[编辑] 考虑到您面临的问题,您实际上并不想使用上述方法。使用 each 方法遍历您的值。正如我所说,这是完成任务的一种天真的方式,您可能想研究一种很好的递归方法,它可以搭载排序算法。
[编辑] 合并同一问题的 2 个答案(效率设计注意事项)
这是一个使用 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)
}