Сортировка числовых строк с использованием итеративного в groovy

#groovy #nexus #artifact

#groovy #nexus #артефакт

Вопрос:

Я хочу отсортировать версию Iterable<Component> components . Как при печати в консоли он показывает мне следующий результат:

 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
 

Это мой код

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

Комментарии:

1. Существуют некоторые сценарии, которые не представлены в вашем примере вывода, чтобы точно знать, каковы требования. components.sort {it.version()} Дает ли желаемый порядок?

2.В вашем заголовке указана сортировка числовых строк, но ваш вывод показывает 1.0.2 , что после 1.0.11 этого, возможно, вашим требованием является альфа-сортировка.

3. «откуда это взялось» — в Groovy, если замыкание не объявляет список аргументов, замыкание примет 1 необязательный аргумент named it . { it.version() } { it -> it.version() } и { comp -> comp.version() } функционально эквивалентны.

4. «components = components.sort { it.size() }» — это допустимый параметр Groovy и не выдаст ошибку во время выполнения, если все элементы в components нем имеют метод с именем size , который не принимает никаких аргументов.

5. Я думал, вы хотите отсортировать по версии, поэтому я предложил components = components.sort { it.version() } .

Ответ №1:

Некоторая простая сортировка по версии может быть выполнена следующим образом:

 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'
 

С принтами

 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
 

Ответ №2:

Другой пример:

 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
}
 

который печатает:

 ─➤ 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
 

Обратите внимание, что это решение также (по крайней мере, более или менее) обрабатывает версии с разным количеством элементов, таких как 10.2 и 1.0.4.2 .