Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort array by filename in groovy

Tags:

sorting

groovy

I'm trying to sort a list of jars by their filenames:

def jars = ['app-5.0.0.jar', 'app-5.1.1.jar', 'app-5.2.0-9.jar', 'app-5.2.0-10.jar', 'app-5.2.0.jar', 'app-5.1.0.jar']
jars = jars.sort().reverse()
println jars

The result is:

[app-5.2.0.jar, app-5.2.0-9.jar, app-5.2.0-10.jar, app-5.1.1.jar, app-5.1.0.jar, app-5.0.0.jar]

However, I'm more interested in the natural (and probably more intuitive) sorting to receive this sorted list:

[app-5.2.0-10.jar, app-5.2.0-9.jar, app-5.2.0.jar, app-5.1.1.jar, app-5.1.0.jar, app-5.0.0.jar]

Is there a way to achieve this?

this is my current algorithm for sorting but it's too verbose in my opinion. However, it really does what I'm looking for. Each part of the version (major, minor, maintenance, build) is evaluated independently:

jars = jars.sort { a, b ->
    File fileA = new File(a)
    File fileB = new File(b)
    def partsA = fileA.name.findAll(/\d+/)
    def partsB = fileB.name.findAll(/\d+/)

    if (partsA[0] == null) partsA[0] = "0"
    if (partsB[0] == null) partsB[0] = "0"
    if (partsA[0].toInteger() < partsB[0].toInteger()) {
        println "${partsA[0]} < ${partsB[0]}"
        return -1
    } else if (partsA[0].toInteger() > partsB[0].toInteger()) {
        println "${partsA[0]} > ${partsB[0]}"
        return 1
    } else {
        if (partsA[1] == null) partsA[1] = "0"
        if (partsB[1] == null) partsB[1] = "0"
        if (partsA[1].toInteger() < partsB[1].toInteger()) {
            println "${partsA[1]} < ${partsB[1]}"
            return -1
        } else if (partsA[1].toInteger() > partsB[1].toInteger()) {
            println "${partsA[1]} > ${partsB[1]}"
            return 1
        } else {
            if (partsA[2] == null) partsA[2] = "0"
            if (partsB[2] == null) partsB[2] = "0"
            if (partsA[2].toInteger() < partsB[2].toInteger()) {
                println "${partsA[2]} < ${partsB[2]}"
                return -1
            } else if (partsA[2].toInteger() > partsB[2].toInteger()) {
                println "${partsA[2]} > ${partsB[2]}"
                return 1
            } else {
                if (partsA[3] == null) partsA[3] = "0"
                if (partsB[3] == null) partsB[3] = "0"
                if (partsA[3].toInteger() < partsB[3].toInteger()) {
                    println "${partsA[3]} < ${partsB[3]}"
                    return -1
                } else if (partsA[3].toInteger() > partsB[3].toInteger()) {
                    println "${partsA[3]} > ${partsB[3]}"
                    return 1
                } else {
                    println "${partsA[3]} = ${partsB[3]}"
                    return 0
                }
            }
        }
    }
}
like image 324
user3105453 Avatar asked Mar 25 '26 17:03

user3105453


1 Answers

Had to try this:

def jars = ['app-5.0.0.jar', 'app-5.1.1.jar', 'app-5.2.0-9.jar', 'app-5.2.0-10.jar', 'app-5.2.0.jar', 'app-5.1.0.jar', 'app-1.0.jar', 'app-0.10.jar']
jars = jars.sort{ -it.findAll( /\d+/ ).join().toInteger() }
println jars

Gets:

[app-5.2.0-10.jar, app-5.2.0-9.jar, app-5.2.0.jar, app-5.1.1.jar, app-5.1.0.jar, app-5.0.0.jar, app-1.0.jar, app-0.10.jar]

Or more thorough version that handles large patch versions:

def jars = ['app-5.0.0.jar', 'app-5.1.1.jar', 'app-5.2.0-9.jar', 'app-5.2.0-10.jar', 'app-5.2.0.jar', 'app-5.1.0.jar', 'app-5.1.1-172.jar']

jars.sort{ a, b -> 
    def aList = a.findAll(/\d+/)
    def bList = b.findAll(/\d+/)

    for ( int i = 0 ; i < aList.size() ; i++ ) {
        def aVal = aList[i] ? aList[i].toInteger() : 0
        def bVal = bList[i] ? bList[i].toInteger() : 0
        if ( aVal <=> bVal ) { // only return if non-zero i.e. not equal
            return aVal <=> bVal
        }
    }

    bList.size() > aList.size() ? -1 : 0 // all facets match up to now, if b has additional parts it must be later version
}

println jars.reverse()

Gets:

[app-5.2.0-10.jar, app-5.2.0-9.jar, app-5.2.0.jar, app-5.1.1-172.jar, app-5.1.1.jar, app-5.1.0.jar, app-5.0.0.jar]
like image 108
Mike W Avatar answered Mar 29 '26 12:03

Mike W



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!