Compare version strings in groovy

后端 未结 11 1907
耶瑟儿~
耶瑟儿~ 2020-11-30 09:50

Hey I have created a Groovy script that will extract the version numbers of some folder. I would then like to compare the version numbers and select the highest.

I g

相关标签:
11条回答
  • 2020-11-30 10:30

    If anyone is using Grails (e.g. Grails 2.2.3), I think VersionComparator already provides exactly what we need.

    If you are not using Grails, you can always Google the source code of this class.

    Example of working tests:

    import org.codehaus.groovy.grails.plugins.VersionComparator
    
    assert ['1.13.4', '1.4.5'].sort( new VersionComparator() ) == ['1.4.5', '1.13.4']
    assert ['3.1.20', '3', '3.0.1', '3.1'].sort( new VersionComparator() ) == ['3', '3.0.1', '3.1', '3.1.20']
    assert ['02.2.02.02', '02.2.03.01', '02.2.02.01'].sort( new VersionComparator() ) == ['02.2.02.01', '02.2.02.02', '02.2.03.01']
    assert ['4', '2'].sort( new VersionComparator() ) == ['2', '4']
    assert ['4.1', '4'].sort( new VersionComparator() ) == ['4', '4.1']
    assert ['4.1', '5'].sort( new VersionComparator() ) == ['4.1', '5']
    
    assert new VersionComparator().compare( '1.13.4', '1.4.5' ) > 0
    assert new VersionComparator().compare( '1.4.5', '1.13.4' ) < 0
    

    Hope this helps.

    0 讨论(0)
  • 2020-11-30 10:30

    Here's a slightly modified version of Nikita's contribution:

    List versions = [ '02.2.02.01', '02.2.02.02', '02.2.03.01']
    String mostRecentVersion = versions.sort {a, b ->
      def a1 = a.tokenize('.')*.toInteger(), b1 = b.tokenize('.')*.toInteger()   
    
      for (i in 0..<[a1.size(), b1.size()].min()){      
        if (a1[i] != b1[i]) {
          return a1[i] <=> b1[i]   
        }
      }
    }[-1]
    
    assert mostRecentVersion == '02.2.03.01'
    
    0 讨论(0)
  • 2020-11-30 10:32

    If we're going for the shortest answer, this must come close ;-)

    String mostRecentVersion( List versions ) {
      versions.sort( false ) { a, b ->
        [a,b]*.tokenize('.')*.collect { it as int }.with { u, v ->
          [u,v].transpose().findResult{ x,y-> x<=>y ?: null } ?: u.size() <=> v.size()
        }
      }[-1]
    }
    
    0 讨论(0)
  • 2020-11-30 10:36

    This appears to work

    String mostRecentVersion(List versions) {
      def sorted = versions.sort(false) { a, b -> 
    
        List verA = a.tokenize('.')
        List verB = b.tokenize('.')
    
        def commonIndices = Math.min(verA.size(), verB.size())
    
        for (int i = 0; i < commonIndices; ++i) {
          def numA = verA[i].toInteger()
          def numB = verB[i].toInteger()
          println "comparing $numA and $numB"
    
          if (numA != numB) {
            return numA <=> numB
          }
        }
    
        // If we got this far then all the common indices are identical, so whichever version is longer must be more recent
        verA.size() <=> verB.size()
      }
    
      println "sorted versions: $sorted"
      sorted[-1]
    }
    

    Here is an inadequate set of tests. You should add some more.

    assert mostRecentVersion(['02.2.02.01', '02.2.02.02', '02.2.03.01']) == '02.2.03.01' 
    assert mostRecentVersion(['4', '2']) == '4'
    assert mostRecentVersion(['4.1', '4']) == '4.1'
    assert mostRecentVersion(['4.1', '5']) == '5'
    

    Run this code and the tests in the Groovy console to verify that it works

    0 讨论(0)
  • 2020-11-30 10:37

    The code I am using with Jenkins ExtendedChoiceParameter (tolerant to non-integer fragments in the version string)

    def vers = ['none']
    new File(this.getBinding().getVariable('dir')).eachDir() { dir -> dirs.add(dir.getName()) }
    
    vers.sort{x, y ->
      def xa = x.tokenize('._-'); def ya = y.tokenize('._-')
      def sz = Math.min(xa.size(), ya.size())
      for (int i = 0; i < sz; ++i) {
        def xs = xa[i]; def ys = ya[i];
        if (xs.isInteger() && ys.isInteger()) {
          def xn = xs.toInteger()
          def yn = ys.toInteger()
          if (xn != yn) { return xn <=> yn }
        } else if (xs != ys) {
          return xs <=> ys
        }
      }
    
      return xa.size() <=> ya.size()
    }.reverse().join(',')
    
    0 讨论(0)
  • 2020-11-30 10:40

    Here my solution:

    def availVersion = "1.5.0.2"
    def ownVersion   = "2.6.0.1"
    
    def availTokens = availVersion.split('\\.')
    def ownTokens   = ownVersion.split('\\.')
    
    def availSize   = availTokens.size()
    def ownSize     = ownTokens.size()
    
    def maxSize     = Math.max(availSize, ownSize)
    
    for (int i = 1; i <= maxSize; i++) {
        def availItem = ((i <= availSize) ? availTokens[i - 1] : 0)
        def ownItem    = ((i <= ownSize)  ? ownTokens[i - 1]   : 0)
    
        print "Avail: ${availItem} -> Own: ${ownItem}\n"
    
        if ((ownItem > availItem) || ( (i == maxSize) && (ownItem >= availItem) )) {
            print "Upgrade NOT needed.\n"
            return
        }
    }
    
    print "Upgrade needed!\n"
    
    0 讨论(0)
提交回复
热议问题