Как отсортировать список по существующим свойствам

Я использую эту строку здесь, чтобы отсортировать список на основе имени объекта.

g.V.sort{it.name}

Как мне отсортировать его по «имени», если оно существует, если нет, я хочу отсортировать его по «названию». Если оба существуют, я хочу сначала отсортировать по «имени», а затем по «названию».

Я не Groovy кодер, поэтому спасибо за помощь заранее.

Ответы на вопрос(3)

Вы можете отсортировать коллекцию, используяComparator.

g.V.sort { a, b ->
    a.name <=> b.name ?: a.title <=> b.title
}

которое, вероятно, пронизано ошибками

def comparator = {o1, o2 ->

  // wording of question suggests title will always exist, if not, add more hasProperty checks  
  def diff = o1.title <=> o2.title

  if (o1.hasProperty('name') && o2.hasProperty('name')) {  
    def nameDiff = o1.name <=> o2.name

    if (nameDiff != 0) {
      diff = nameDiff
    }
  } 
  diff

} as Comparator


def someList = []
// populate the list...    
someList.sort(comparator)

что правильно понял ваш вопрос. Может быть, что-то вроде этого, что вы ищете:

def things = [
    [name: 'aaa', title: '222'],
    [name: 'aaa', title: '333'],
    [title: '222'],
    [title: '111'],
    [name: 'bbb', title: '111'],
    [title: '333'],
    [name: 'aaa', title: '111'],
]

things.sort { a, b ->
    // Compare by name and then by title.
    a.name <=> b.name ?: a.title <=> b.title
}

assert things == [
    [title: '111'],
    [title: '222'],
    [title: '333'],
    [name: 'aaa', title: '111'],
    [name: 'aaa', title: '222'],
    [name: 'aaa', title: '333'],
    [name: 'bbb', title: '111'],
]

То, что происходит внутри этой, казалось бы, невинной функции сравнения, на самом деле довольно много волшебства синтаксиса Groovy. Но это не так уж сложно следовать.

Во-первых,sort Метод вызывается с помощью двоичной функции, которая действует как компаратор (т.е. принимает два аргумента, a и b и возвращает -1, если a <b, 1, если a> b, и 0, если a == b).

Это анонимная функция:{ a, b -> a.name <=> b.name ?: a.title <=> b.title } использует "оператор космического корабля"(<=>... это человек из космического корабля!) чтобы сначала сравнить a и b по именам.

Если имена равны (или оба равны нулю), то результатa.name <=> b.name 0, что неверно оценивается вЭлвис оператор"(?:... представьте, как смайлик), так что результатa.title <=> b.title возвращается

В противном случае, если результат сравнения имени не равен 0, то это верно оценивается в операторе Элвиса, и это значение возвращается.

Это все с учетом того, что вы можете сравнить нулевые значения со строками и что'any string' > null всегда держится (это то же самое, что сказать, что'any string' <=> null == 1).

Таким образом, окончательный результат состоит в том, что элементы без имени сначала сортируются по заголовку, а затем элементы с именем и заголовком упорядочиваются сначала по имени, а затем по заголовку.

Я надеюсь, что это было то, что вы искали. Если вы ожидали другого упорядочения отсортированных элементов, не стесняйтесь уточнить это в комментариях :)

Обновить

Существует также не очень документальноOrderBy объект, который можно использовать в этом случае:

things.sort new OrderBy([{it.name}, {it.title}])
 epidemian05 мар. 2012 г., 13:24
@ Дон Вероятно. Вопрос не указывает, означает ли «не существует», что свойство имеет значение null (или пустую строку) или что свойства с таким именем не существует. Поэтому я выбрал самый простой маршрут = D
 Dónal05 мар. 2012 г., 17:21
Я полагаю, вы могли бы интерпретировать «если он существует», чтобы означать «не нуль», как очень удобно для вас :)
 Dónal05 мар. 2012 г., 11:22
это решение вызовет исключение, если объекты не имеютname свойство, но вопрос говорит "сортировать его на основе" имени "если он существует"

Ваш ответ на вопрос