Мне нужно отсортировать коллекцию Лица по двум параметрам, по фамилиям и по именам. Как я могу сделать что-то подобное в OCL?Как сортировать два параметра в OCL?
ответ
Функция sortedBy
сортирует элементы, используя критерии, выраженные в ее теле, и связь между каждым собранным результатом <
.
В вашем случае, если предположить, что у вас есть атрибут surname
, следующий оператор будет сортировать коллекцию c
с помощью оператора <
на каждой фамилии собрались (так <
на струнах):
c->sortedBy(p | p.surname)
идея может чтобы вычислить уникальную строку, используя фамилию и имя, конкатенированное с ним. Таким образом, если у вас есть:
- George Smith
- Garry Smith
- Джордж SMath
Сравнение будет сделано между "Smith_George", "Smith_Garry" и "Smath_George" и будет заказал, после лексикографического порядка, чтобы:
- Джорджа SMath (Sm т h_George)
- Garry Smith (Smith_G RRY)
- Джордж Смит (smith_G е огр)
Наконец, запрос OCL будет (при условии surname
и name
как существующие атрибуты):
c->sortedBy(p | p.surname + '_' + p.name)
Этот небольшой трюк выполняет эту работу, но это не «точно» сравнение двух параметров для sortedBy.
OCL sortedBy (lambda), по-видимому, сильно отличается от сорта Java (компаратора), по-видимому, требуя проекции объектов в качестве метрики для сортировки. Однако, если проекция является «я», у вас есть другая функциональность Java. Поэтому, если вы отсортировалиBy (p | p), сортировка зависит от операции < для p.
Для облегчения этого прототип Eclipse OCL будущего OCL вводит тип OclComparable с методом compareTo, позволяющим реализовать все реляционные операции, если ваш настраиваемый тип расширяет тип OclComparable.
(Аналогичный OclSummable с нуля() и сумма() действует поддерживает Collection :: сумму() в общем,., Например, строка реализует сумму в виде конкатенации)
Спасибо вы вдохновили меня. Я только что поднял http://issues.omg.org/browse/OCL25-213, текст которого:
Итерация sortedBy обеспечивает элегантное решение проблемы сортировки, в которой метрика сортировки является проекцией отсортированного объекта. Таким образом, sortedBy (p | p.name) или просто sortedBy (имя) является коротким и позволяет избежать опечаток из более условного изложения, включающего сравнение двух объектов.Естественное решение вполне может быть эффективным для больших коллекций с нетривиальными метриками.
Однако решение sortedBy не знакомо и настолько запутанно для новичков и не подходит для многокварной сортировки, для чего может потребоваться построить отдельный ключ из искусственного компаунда.
Одним из решений может быть, чтобы обеспечить более обычного итератора, такие как вид (p1, p2 | сравнение выражение), допускающие два ключа сортировки:
рода (p1, p2 | пусть diff1 = p1.key1.compareTo (p2.key1) в если diff1 <> 0 разн 1 еще p1.key2.compareTo (p2.key2) ENDIF)
Однако это имеет плохую читаемость и широкие возможности для опечаток.
В качестве альтернативы sortedBy с кортежем-значной метрикой может поддерживать несколько ключей, как:
sortedBy (набор {первого = key1, второй = key2})
(алфавитный порядок названий кортежа части определяет приоритет.)
(с sortedBy является декларативно ясно и компактным, неэффективным малым/тривиальными реализации могут быть оптимизированы для их рода() эквиваленты.)
мне кажется, что это решение не будет работать во всех случаях, Мне нужно что-то унив ersal. Это решение будет неправильным, если у нас есть, например, две даты. Например, дата начала проекта и дата завершения проекта. Что я могу использовать в таких случаях? – DM14
Как я уже сказал, это решение работало в вашем конкретном случае, используя имя/фамилию, это будет использовать лексикографический порядок. Я не уверен, но я не думаю, что функция OCL sortedBy может выполнять этот поиск по двум критериям. В других случаях необходимо найти еще один трюк, в примере с датой начала и окончания вы можете вычислить время, затрачиваемое каждым проектом, с использованием даты окончания/начала и сортировки по этим критериям. В противном случае, переводя дату в формате yyy-mm-dd (со знаковым 0 obvioulsy), должен работать трюк с лексикографическим порядком. –