Отличный. Сортировать массив карт по ключу вложенной карты внутри

Как мне написать какой-нибудь отличный скрипт для возврата массива имен (name), отсортированных по ключу created_at, вложенному в ключ commit?

Используя это в качестве образца данных:

[
{"name":"v10.8.0-rc13",
"message":"Version v10.8.0-rc13",
"target":"171b50a40984c358a07c7e37ee95f8d788718198",
"commit":
 {
 "id":"1b3911c3cc8e72cc93370a90a597e2a0b944bcc2",
 "short_id":"1b3911c3",
 "title":"Update VERSION to 10.8.0-rc13",
 "created_at":"2018-05-18T12:43:58.000+01:00",       <------ I WANT TO SORT BY THIS 
 "parent_ids":["a7090d00098a4acc03cfc2b01df8019c918bd0bc"],
 "message":"Update VERSION to 10.8.0-rc13\n",
 "author_name":"Filipa Lacerda",
 "author_email":"[email protected]",
 "authored_date":"2018-05-18T12:43:58.000+01:00",
 "committer_name":"Filipa Lacerda",
 "committer_email":"[email protected]",
 "committed_date":"2018-05-18T12:43:58.000+01:00"
  },
"release":null
},
.
.
.
]

Пока что я использую что-то вроде этого, чтобы получить список несортированных имен:

List<String> tags= new ArrayList<String>()

def url="curl -X GET http://blah_blah"
def payload = url.execute().text
def slurper = new JsonSlurper()
def response = slurper.parseText(payload)

for(item in response)
{
   tags.add(item.name)
}

println(tags)

В этом случае response имеет тип java.util.ArrayList

а response[0] относится к типу groovy.json.internal.LazyMap

Все примеры, которые я нашел до сих пор, используют методы .sort или .SortBy, которые не работают на LazyMap. **ОБНОВЛЕНИЕ** Я не думаю, что это верно утверждение.


person frakman1    schedule 18.05.2018    source источник


Ответы (1)


Чтобы получить список имен тегов из такой структуры, вы можете использовать оператор распространения Groovy:

def tags = response*.name

Его можно упростить до:

def tags = response.name

и это просто эквивалент:

def tags = response.collect { it.name }

Теперь, если вы ожидаете, что этот список будет отсортирован по ключу commit.created_at, вы можете вызвать метод .sort {} перед использованием оператора распространения, например.

def tags = response.sort { it.commit.created_at }.name

Он отсортирует список имен в порядке возрастания. Если вас интересует порядок убывания, вы можете отменить метод тела сортировки:

def tags = response.sort { !it.commit.created_at }.name

Ниже вы можете найти полный пример:

import groovy.json.JsonSlurper

def json = "https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab-ce/repository/tags".toURL().text

def response = new JsonSlurper().parseText(json)

def tags = response.sort { it.commit.created_at }.name

println tags

Выход:

[v10.7.0, v10.8.0.pre, v10.7.1, v10.5.8, v10.6.5, v10.7.2, v10.8.0-rc1, v10.7.3, v10.8.0-rc2, v10.8.0-rc3, v10.8.0-rc4, v10.8.0-rc6, v10.8.0-rc5, v10.8.0-rc7, v10.8.0-rc8, v10.8.0-rc9, v10.8.0-rc10, v10.8.0-rc11, v10.8.0-rc12, v10.8.0-rc13]

Надеюсь, поможет.

person Szymon Stepniak    schedule 18.05.2018
comment
Спасибо @Szymon! Думаю, я заработал, используя это: response.sort { a,b -> a.commit.created_at <=> b.commit.created_at } Звучит правильно? - person frakman1; 18.05.2018
comment
@ frakman1 Это эквивалент response.sort { it.commit.created_at }. Единственное отличие состоит в том, что { a,b -> a.commit.created_at <=> b.commit.created_at } — это замыкание, представляющее объект Comparator. - person Szymon Stepniak; 18.05.2018
comment
Спасибо за понимание и понятное объяснение. Я получаю это сейчас. - person frakman1; 18.05.2018