比较 groovy 中的版本字符串

发布于 2024-12-09 07:58:59 字数 448 浏览 0 评论 0原文

嘿,我创建了一个 Groovy 脚本,它将提取某些文件夹的版本号。然后我想比较版本号并选择最高的。

我让我的脚本通过 dir 文件夹运行,然后获取以下格式的版本: 02.2.02.01

所以我可以获得如下内容:

  • 02.2.02.01
  • 02.2.02.02
  • 02.2.03.01

我不' t 将它们作为列表,但像这样:

baseDir.listFiles().each { file -> 
  def string = file.getName().substring(5, 15)
  // do stuff
}

我还测试了 Groovy 可以将它们与 > 运算符进行比较,并且它 能!但现在我需要选择版本最高的那个

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 got my script to run through the dir folder and I then get the versions in this format: 02.2.02.01

So I could get something like this:

  • 02.2.02.01
  • 02.2.02.02
  • 02.2.03.01

I don't have them as a list but like this:

baseDir.listFiles().each { file -> 
  def string = file.getName().substring(5, 15)
  // do stuff
}

Also I have tested that Groovy could compare them with the > operator and it can! But now I need to select the one with the highest version

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

风筝在阴天搁浅。 2024-12-16 07:58:59

这似乎有效

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()
      
      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]
}

这是一组不充分的测试。你应该再添加一些。

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'

在 Groovy 控制台中运行此代码和测试以验证其是否有效

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()
      
      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

千柳 2024-12-16 07:58:59

如果我们想要最短的答案,这必须接近;-)

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]
}

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]
}
草莓酥 2024-12-16 07:58:59

我的是最短的!哈哈 )

versions = 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]
  0
}

Mine is the shortest! lol )

versions = 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]
  0
}
幸福不弃 2024-12-16 07:58:59

如果有人使用 Grails(例如 Grails 2.2.3),我认为 VersionComparator 已经提供了我们所需要的东西。

如果您不使用 Grails,您可以随时 Google 搜索此类的源代码。

工作测试示例:

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

希望这有帮助。

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.

撩人痒 2024-12-16 07:58:59
String maxVersion(versions) {
    versions.max { 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()
            if (numA != numB) {
                return numA <=> numB
            }
        }
        verA.size() <=> verB.size()
    }
}
String maxVersion(versions) {
    versions.max { 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()
            if (numA != numB) {
                return numA <=> numB
            }
        }
        verA.size() <=> verB.size()
    }
}
睡美人的小仙女 2024-12-16 07:58:59

这是对 Tim 答案的修改,它采用两个版本字符串并返回一个布尔值(如果第一个版本比第二个版本更新,则为 true)

String v1 = '02.2.01.02'
String v2 = '02.2.06.02'

boolean isMoreRecent( String a, String b ) {
    [a,b]*.tokenize('.')*.collect { it as int }.with { u, v ->
       Integer result = [u,v].transpose().findResult{ x,y -> x <=> y ?: null } ?: u.size() <=> v.size()
       return (result == 1)
    } 
}

assert !isMoreRecent(v1,v2)
assert isMoreRecent(v2,v1)​

Here is a modification of Tim's answer which takes two version strings and returns a boolean (true if the first is newer than the second)

String v1 = '02.2.01.02'
String v2 = '02.2.06.02'

boolean isMoreRecent( String a, String b ) {
    [a,b]*.tokenize('.')*.collect { it as int }.with { u, v ->
       Integer result = [u,v].transpose().findResult{ x,y -> x <=> y ?: null } ?: u.size() <=> v.size()
       return (result == 1)
    } 
}

assert !isMoreRecent(v1,v2)
assert isMoreRecent(v2,v1)​
如果没结果 2024-12-16 07:58:59

我与 Jenkins ExtendedChoiceParameter 一起使用的代码(容忍版本字符串中的非整数片段)

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(',')

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(',')
感性不性感 2024-12-16 07:58:59

这是我的解决方案:

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"

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"
聽兲甴掵 2024-12-16 07:58:59

我在Android Studio 3.0 Beta 7中使用gradle 4.1。有VersionNumber.java(在C:\Users\ssfang.gradle\wrapper\dists\gradle-4.1-all\bzyivzo6n839fup2jbap0tjew\gradle-4.1\src\core\org\gradle下\util)

例如:

apply plugin: 'com.android.application'

try{ // undocumented
    println "${android.plugin.getSdkFolder().getAbsolutePath()}"
    // Since 1.3.1 or 1.5.0? android studio version or android gradle plugin?
    println "${android.getSdkDirectory().getAbsolutePath()}"
}catch (ignored){
}

// As of android gradle plugin v2.1.2
println android.sdkDirectory.path
println android.ndkDirectory.path
def buildToolsVer = new File(android.sdkDirectory.path, 'build-tools').listFiles().collect{ VersionNumber.parse(it.getName()) }.sort()
println buildToolsVer
printf('%s, %s\n',  buildToolsVer.head(), buildToolsVer.last().toString())

def String mostRecentVersion(List<String> versions) {
//   TreeMap<VersionNumber, String> verNum2StrMap = versions.collectEntries(new TreeMap(), { [VersionNumber.parse(it), it] })

//    TreeMap<VersionNumber, String> verNum2StrMap = versions.inject(new TreeMap()) { memo, entry ->
//        memo[VersionNumber.parse(entry)] = entry
//        memo
//    }

    TreeMap<VersionNumber, String> verNum2StrMap = versions.inject(new TreeMap()) { map, verStr ->
        map << [(VersionNumber.parse(verStr)): verStr]
    }

    // println verNum2StrMap.lastEntry().value
    verNum2StrMap.lastEntry().value
}

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'

android {
    compileSdkVersion 25
    buildToolsVersion "26.0.2"
    defaultConfig {
        applicationId "ss.xsigner"
        minSdkVersion 14
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        setProperty("archivesBaseName", "xsigner")
    }
}

--

在此处输入图像描述

在此处输入图像描述

I use gradle 4.1 in Android Studio 3.0 Beta 7. There is VersionNumber.java (under C:\Users\ssfang.gradle\wrapper\dists\gradle-4.1-all\bzyivzo6n839fup2jbap0tjew\gradle-4.1\src\core\org\gradle\util)

For example:

apply plugin: 'com.android.application'

try{ // undocumented
    println "${android.plugin.getSdkFolder().getAbsolutePath()}"
    // Since 1.3.1 or 1.5.0? android studio version or android gradle plugin?
    println "${android.getSdkDirectory().getAbsolutePath()}"
}catch (ignored){
}

// As of android gradle plugin v2.1.2
println android.sdkDirectory.path
println android.ndkDirectory.path
def buildToolsVer = new File(android.sdkDirectory.path, 'build-tools').listFiles().collect{ VersionNumber.parse(it.getName()) }.sort()
println buildToolsVer
printf('%s, %s\n',  buildToolsVer.head(), buildToolsVer.last().toString())

def String mostRecentVersion(List<String> versions) {
//   TreeMap<VersionNumber, String> verNum2StrMap = versions.collectEntries(new TreeMap(), { [VersionNumber.parse(it), it] })

//    TreeMap<VersionNumber, String> verNum2StrMap = versions.inject(new TreeMap()) { memo, entry ->
//        memo[VersionNumber.parse(entry)] = entry
//        memo
//    }

    TreeMap<VersionNumber, String> verNum2StrMap = versions.inject(new TreeMap()) { map, verStr ->
        map << [(VersionNumber.parse(verStr)): verStr]
    }

    // println verNum2StrMap.lastEntry().value
    verNum2StrMap.lastEntry().value
}

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'

android {
    compileSdkVersion 25
    buildToolsVersion "26.0.2"
    defaultConfig {
        applicationId "ss.xsigner"
        minSdkVersion 14
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        setProperty("archivesBaseName", "xsigner")
    }
}

--

enter image description here

enter image description here

树深时见影 2024-12-16 07:58:59

这是 Nikita 贡献的稍微修改的版本:

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'

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'
琉璃梦幻 2024-12-16 07:58:59

如果您只需要实现 Comparable 或 Comparator 接口,这是我根据其他答案提出的最短解决方案:

    [first, second]*.tokenize('.').with { a, b ->
        [a, b].transpose().findResult { x, y -> x <=> y ?: null } ?: a.size() <=> b.size()
    }

If you just need to implement Comparable or Comparator interface here's the shortest solution I came up with based on the other answers:

    [first, second]*.tokenize('.').with { a, b ->
        [a, b].transpose().findResult { x, y -> x <=> y ?: null } ?: a.size() <=> b.size()
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文