Svetoslav Panteleev
Svetoslav Panteleev

Reputation: 119

Numeric string sorting using Iterable<Component> in groovy

I want to sort version from Iterable<Component> components. Нow when i print in the console it shows me the following result:

artifact 1.0.1
artifact 1.0.10
artifact 1.0.11
artifact 1.0.12
artifcat 1.0.2
artifcat 1.0.3
artifcat 1.0.4

This is my code

import org.sonatype.nexus.repository.storage.Component
import org.sonatype.nexus.repository.storage.Query
import org.sonatype.nexus.repository.storage.StorageFacet

def repoName = "artifact"

log.info("delete components for repository: " + repoName)


def repo = repository.repositoryManager.get(repoName)
def tx = repo.facet(StorageFacet).txSupplier().get()
try {
tx.begin()
    Iterable<Component> components = tx.findComponents(Query.builder()
      .where('version < ').param('1.1.0')
      .build(), [repo])
    tx.commit()
    
    for(Component c : components) {
        log.info("Name " + c.name() + " Version" + c.version())
    }
} catch (Exception e) {
    log.warn("Transaction failed {}", e.toString())
    tx.rollback()
} finally {
    tx.close()
}

Upvotes: 0

Views: 191

Answers (2)

Matias Bjarland
Matias Bjarland

Reputation: 4482

Another example:

def components = '''\
artifact 1.2.1
artifact 1.0.1
artifact 1.0.10
artifact 2.0.10
artifact 10.2
artifact 1.0.11
artifact 1.0.12
artifact 1.4.12
artifcat 1.0.2
artifcat 1.0.3
artifcat 1.0.4
artifact 1.0.4.2'''.readLines()*.tokenize(' ').collect { name, version ->
  [name: name, version: version]
}

def sorted = components.sort { a, b ->
  def f = { it.version.tokenize('.')*.toInteger() }
  [f(a), f(b)].transpose().findResult { ai, bi -> 
    ai <=> bi ?: null 
  } ?: a.version <=> b.version
}

sorted.each { c -> 
    println c.version
}

which prints:

─➤ groovy solution.groovy
1.0.1
1.0.2
1.0.3
1.0.4
1.0.4.2
1.0.10
1.0.11
1.0.12
1.2.1
1.4.12
2.0.10
10.2

Note that this solution also (at least more or less) handles versions with differing numbers of elements such as 10.2 and 1.0.4.2.

Upvotes: 0

injecteer
injecteer

Reputation: 20699

Some simple sorting by version can be done as follows:

def components = []
'''\
artifact 1.2.1
artifact 1.0.1
artifact 1.0.10
artifact 2.0.10
artifact 1.0.11
artifact 1.0.12
artifact 1.4.12
artifcat 1.0.2
artifcat 1.0.3
artifcat 1.0.4'''.splitEachLine( ' ' ){ name, version ->
  components << [ name:name, version:version ]
}

// augment each component with numeric represenation of version
components.each{
  it.versionNumeric = it.version.split( /\./ )*.toInteger().reverse().withIndex().sum{ num, pow -> 100.power( pow ) * num }
}

components.sort{ it.versionNumeric }*.version.join '\n'

prints

1.0.1
1.0.2
1.0.3
1.0.4
1.0.10
1.0.11
1.0.12
1.2.1
1.4.12
2.0.10

Upvotes: 1

Related Questions