xsl:sort ⚡️ XSLT с примерами кода
При преобразовании документа элементами xsl:for-each
и xsl:apply-templates
, выбранные узлы по умолчанию обрабатываются в порядке просмотра документа, который зависит от выражения, использованного в атрибуте select
этих элементов. XSLT позволяет изменять этот порядок посредством использования механизма сортировки.
Элементы xsl:for-each
и xsl:apply-templates
могут содержать один или несколько элементов xsl:sort
, которые позволяют предварительно сортировать обрабатываемое множество узлов.
Синтаксис
<xsl:sort select="string-expression" lang="nmtoken" data-type="text | number | qname-but-not-ncname" order="ascending | descending" case-order="upper-first | lower-first" />
Атрибуты:
select
- обязательный атрибут, значением которого является выражение, называемое также ключевым выражением.
.
«, что означает, что в качестве значения ключа для каждого узла используется его строковое значение. order
- необязательный атрибут, определяет порядок, в котором узлы должны сортироваться по своим ключам. Этот атрибут может принимать только два значения — «
ascending
«, указывающее на восходящий порядок сортировки, и «descending
«, указывающее на нисходящий порядок. Значением по умолчанию является «ascending
«, то есть восходящий порядок. lang
- необязательный атрибут, определяет язык ключей сортировки. Дело в том, что в разных языках символы алфавита могут иметь различный порядок, что, соответственно, должно учитываться при сортировке. Атрибут
lang
в XSLT может иметь те же самые значения, что и атрибутxml:lang
(например: «en
«, «en-us
«, «ru
» и т. д.). Если значение этого атрибута не определено, процессор может либо определять язык исходя из параметров системы, либо сортировать строки исходя из порядка кодов символовUnicode
. data-type
- необязательный атрибут, определяет тип данных, который несут строковые значения ключей. Техническая рекомендация XSLT разрешает этому атрибуту иметь следующие значения:
- «
text
» — ключи должны быть отсортированы в лексикографическом порядке исходя из языка, определенного атрибутомlang
или параметрами системы. Это значение используется по умолчанию;
- «
- «
number
» — ключи должны сравниваться в численном виде. Если строковое значение ключа не является числом, оно будет преобразовано к не-числу (
), и, поскольку нечисловые значения неупорядочены, соответствующий узел может появиться в отсортированном множестве где угодно;
- «
- «
имя
» — в целях расширяемости XSLT также позволяет указывать в качестве типа данных произвольное имя. В этом случае реализация сортировки полностью зависит от процессора.
- «
case-order
- необязательный атрибут, указывает на порядок сортировки символов разных регистров. Значениями этого атрибута могут быть «
upper-first
«, что означает, что заглавные символы должны идти первыми, или «lower-first
«, что означает, что первыми должны быть строчные символы. К примеру, строки «ночь», «Улица», «фонарь», «Аптека», «НОЧЬ», «Фонарь» при использованииcase-order="upper-first"
будут иметь порядок «Аптека», «НОЧЬ», «ночь», «Фонарь», «фонарь», «улица». При использованииcase-order="lower-first"
те же строки будут идти в порядке «Аптека», «ночь», «НОЧЬ», «фонарь», «Фонарь», «улица». Значениеcase-order
по умолчанию зависит от процессора и языка сортировки. В большинстве случаев заглавные буквы идут первыми.
Описание и примеры
В случае если xsl:for-each
и xsl:apply-templates
содержат элементы xsl:sort
, обработка множества узлов должна производиться не в порядке просмотра документа, а в порядке, который определяется ключами, вычисленными при помощи xsl:sort
. Первый элемент xsl:sort
Как можно видеть, элемент xsl:sort
определяет сортировку достаточно гибко, но вместе с тем не следует забывать, что эти возможности могут быть реализованы в процессорах далеко не полностью. Поэтому одна и та же сортировка может быть выполнена в разных процессорах по-разному.
Приведем простой пример сортировки имен и фамилий.
Пример
Листинг 8.10. Входящий документ
<list> <person> <name>William</name> <surname>Gibson</surname> </person> <person> <name>William</name> <surname>Blake</surname> </person> <person> <name>John</name> <surname>Fowles</surname> </person> </list>
Отсортируем этот список сначала по именам в убывающем, а затем по фамилиям в возрастающем порядке.
<xsl:template match="list"> <xsl:copy> <xsl:for-each select="person"> <xsl:sort select="name" order="descending" /> <xsl:sort select="surname" /> <xsl:copy-of select="." /> </xsl:for-each> </xsl:copy> </xsl:template>
Листинг 8.12. Выходящий документ
<list> <person> <name>William</name> <surname>Blake</surname> </person> <person> <name>William</name> <surname>Gibson</surname> </person> <person> <name>John</name> <surname>Fowles</surname> </person> </list>
К сожалению, сортировкой нельзя управлять динамически. Все атрибуты элемента xsl:sort
должны обладать фиксированными значениями.
Ссылки
xsl:sort
MDN (рус.)xsl:sort
MSDN (en)
Python List sort()
В этом руководстве мы узнаем о методе Python sort() с помощью примеров.
Метод sort()
сортирует элементы списка в порядке возрастания или убывания.
Пример
prime_numbers = [11, 3, 7, 5, 2]# сортировка списка по возрастанию prime_numbers.sort()
печать (простые_числа) # Вывод: [2, 3, 5, 7, 11]
sort() Синтаксис
Синтаксис sort() 9Метод 0006:
list.sort(key=..., reverse=...)
В качестве альтернативы вы также можете использовать встроенную функцию Python sorted() для той же цели.
sorted(list, key=..., reverse=...)
Примечание: Простейшее различие между sort()
и sorted()
заключается в следующем: sort()
изменяет список напрямую и не возвращает никакого значения, а sorted()
не изменяет список и возвращает отсортированный список.
Параметры sort()
По умолчанию sort()
не требует дополнительных параметров. Однако у него есть два необязательных параметра:
- reverse - Если
True
, отсортированный список инвертируется (или сортируется в порядке убывания) - ключ - функция, служащая ключом для сравнения сортировки
sort() Возвращаемое значение
Метод sort()
не возвращает никакого значения. Скорее, он изменяет первоначальный список.
Если вы хотите, чтобы функция возвращала отсортированный список, а не изменяла исходный список, используйте sorted()
.
Пример 1: Сортировка заданного списка
# список гласных гласные = ['e', 'a', 'u', 'o', 'i']# отсортировать гласные гласные.sort()
# печатать гласные print('Сортированный список:', гласные)
Вывод
Отсортированный список: ['a', 'e', 'i', 'o', 'u']
Сортировка в порядке убывания
sort() 9Метод 0006 принимает обратный параметр
в качестве необязательного аргумента.
Параметр reverse = True
сортирует список в порядке убывания.
list.sort(reverse=True)
В качестве альтернативы sorted()
вы можете использовать следующий код.
sorted(list, reverse=True)
Пример 2. Сортировка списка по убыванию
# список гласных гласные = ['e', 'a', 'u', 'o', 'i']# отсортировать гласные vowels. sort(reverse=True)
# печатать гласные print('Отсортированный список (по убыванию):', гласные)
Вывод
Отсортированный список (по убыванию): ['u', 'o', 'i', 'e', 'a']
Сортировка с помощью пользовательской функции с помощью клавиши
Если вы хотите свою собственную реализацию для сортировки, метод sort()
также принимает функцию key
в качестве необязательного параметра.
По результатам работы ключевой функции можно отсортировать заданный список.
list.sort(key=len)
В качестве альтернативы sorted:
sorted(list, key=len)
Здесь len
— встроенная функция Python для подсчета длины элемента.
Список отсортирован по длине каждого элемента, от меньшего к большему.
Мы знаем, что кортеж по умолчанию сортируется по первому параметру. Давайте посмотрим, как настроить метод sort()
для сортировки с использованием второго элемента.
Пример 3: Сортировка списка с помощью клавиши
# взять второй элемент для сортировки Def TakeSecond (элемент): возврат элемента[1] # случайный список случайный = [(2, 2), (3, 4), (4, 1), (1, 3)]# отсортировать список по ключу random.sort(key=takeSecond)
# распечатать список print('Сортированный список:', random)
Вывод
Отсортированный список: [(4, 1), (2, 2), (1, 3), (3, 4)]
Возьмем другой пример. Предположим, у нас есть список информации о сотрудниках офиса, где каждый элемент является словарем.
Список можно отсортировать следующим образом:
# сортировка по пользовательскому ключу сотрудники = [ {'Имя': 'Алан Тьюринг', 'возраст': 25, 'зарплата': 10000}, {'Имя': 'Шарон Лин', 'возраст': 30, 'зарплата': 8000}, {'Имя': 'Джон Хопкинс', 'возраст': 18, 'зарплата': 1000}, {'Имя': 'Михаил Таль', 'возраст': 40, 'зарплата': 15000}, ] # пользовательские функции для получения информации о сотрудниках def get_name (сотрудник): вернуть сотрудника. get('Имя') def get_age (сотрудник): вернуть сотрудника.get('возраст') def get_salary (сотрудник): вернуть employee.get('зарплата')# сортировать по имени (по возрастанию) employee.sort(key=get_name)
печать (сотрудники, конец = '\n\n')# сортировать по возрасту (по возрастанию) employee.sort (ключ = get_age)
печать (сотрудники, конец = '\n\n')# сортировать по зарплате (По убыванию) employee.sort (key = get_salary, reverse = True)
print(employees, end='\n\n')
Вывод
[{'Имя': 'Алан Тьюринг', 'возраст': 25, 'зарплата': 10000}, {'Имя': 'Джон Хопкинс', 'возраст': 18, 'зарплата': 1000}, {' Имя': 'Михаил Таль', 'возраст': 40, 'зарплата': 15000}, {'Имя': 'Шарон Лин', 'возраст': 30, 'зарплата': 8000}] [{'Имя': 'Джон Хопкинс', 'возраст': 18, 'зарплата': 1000}, {'Имя': 'Алан Тьюринг', 'возраст': 25, 'зарплата': 10000}, {'Имя ': 'Шарон Лин', 'возраст': 30, 'зарплата': 8000}, {'Имя': 'Михаил Таль', 'возраст': 40, 'зарплата': 15000}] [{'Имя': 'Михаил Таль', 'возраст': 40, 'зарплата': 15000}, {'Имя': 'Алан Тьюринг', 'возраст': 25, 'зарплата': 10000}, {'Имя ': 'Шарон Лин', 'возраст': 30, 'зарплата': 8000}, {'Имя': 'Джон Хопкинс', 'возраст': 18, 'зарплата': 1000}]
Здесь, для первого случая, наша пользовательская функция возвращает имя каждого сотрудника.
, Python по умолчанию сортирует ее в алфавитном порядке. Во втором случае возраст ( int
) возвращается и сортируется в порядке возрастания.
В третьем случае функция возвращает зарплату ( int
) и сортирует в порядке убывания, используя reverse = True
.
Рекомендуется использовать лямбда-функцию, если ее можно описать одной строкой. Таким образом, мы также можем написать приведенную выше программу как:
# сортировка по пользовательскому ключу сотрудники = [ {'Имя': 'Алан Тьюринг', 'возраст': 25, 'зарплата': 10000}, {'Имя': 'Шарон Лин', 'возраст': 30, 'зарплата': 8000}, {'Имя': 'Джон Хопкинс', 'возраст': 18, 'зарплата': 1000}, {'Имя': 'Михаил Таль', 'возраст': 40, 'зарплата': 15000}, ]# сортировать по имени (по возрастанию) employee.sort (key = lambda x: x.get («Имя»))
печать (сотрудники, конец = '\n\n')# сортировать по возрасту (по возрастанию) employee. sort (key = lambda x: x.get ('возраст'))
печать (сотрудники, конец = '\n\n')# сортировать по зарплате (По убыванию) employee.sort (key = lambda x: x.get («зарплата»), reverse = True)
print(employees, end='\n\n')
Вывод
[{'Имя': 'Алан Тьюринг', 'возраст': 25, 'зарплата': 10000}, {'Имя': 'Джон Хопкинс', 'возраст': 18, 'зарплата': 1000}, {' Имя': 'Михаил Таль', 'возраст': 40, 'зарплата': 15000}, {'Имя': 'Шарон Лин', 'возраст': 30, 'зарплата': 8000}] [{'Имя': 'Джон Хопкинс', 'возраст': 18, 'зарплата': 1000}, {'Имя': 'Алан Тьюринг', 'возраст': 25, 'зарплата': 10000}, {'Имя ': 'Шарон Лин', 'возраст': 30, 'зарплата': 8000}, {'Имя': 'Михаил Таль', 'возраст': 40, 'зарплата': 15000}] [{'Имя': 'Михаил Таль', 'возраст': 40, 'зарплата': 15000}, {'Имя': 'Алан Тьюринг', 'возраст': 25, 'зарплата': 10000}, {'Имя ': 'Шарон Лин', 'возраст': 30, 'зарплата': 8000}, {'Имя': 'Джон Хопкинс', 'возраст': 18, 'зарплата': 1000}]
Рекомендуемые показания
- Python Lambda
- Python sorted()
mysql — Сортировать записи по; будущее ASC, прошлое DESC
спросил
Изменено 4 года, 9 месяцев назад
Просмотрено 1к раз
Я хочу отсортировать записи следующим образом:
- Будущие/настоящие события ASC
- Прошлые события DESC
Итак, сначала сегодня, потом завтра, пока не будет больше будущих записей. Затем я хочу показать прошедшие события, но сначала последние.
Пока нашел решение для первого пункта:
ЗАКАЗАТЬ ПО ( СЛУЧАЙ, КОГДА ev.StartDate < CURDATE() ТОГДА 1 ИНАЧЕ 0 КОНЕЦ) ASC, ev.StartDate ASC
Но проблема с этим запросом заключается в том, что все сообщения упорядочены по ASC, включая прошлые сообщения (которые должны быть DESC).
Как совместить это в CASE
?
- MySQL
- SQL
1
Вам нужен немного более сложный заказ по
:
ЗАКАЗАТЬ ПО (ev.StartDate < CURDATE()), (случай, когда ev.StartDate > CURDATE(), затем ev.StartDate end) ASC, (случай, когда ev.StartDate < CURDATE(), тогда ev.StartDate end) DESC
На самом деле это можно сделать с помощью двух предложений:
ЗАКАЗАТЬ ПО наибольшей (ev.StartDate, CURDATE()) DESC, минимум (ev.StartDate, CURDATE()) ASC
Но я думаю, что первая версия более понятна по своему замыслу.