Сортировка с помощью функции
В уроке про списки table.sort(t) сортировала числа от меньшего к большему, а строки — по кодам символов. Дело в том, что table.sort сравнивает элементы с помощью <. Чтобы отсортировать их как-то иначе, передайте второй аргумент: функцию, которая сравнивает два элемента. table.sort вызывает её снова и снова с двумя элементами, a и b, а функция возвращает true, когда a должен стоять перед b:
local harvest = {12, 30, 7, 45, 18}
table.sort(harvest, function(a, b)
return a > b
end)
print(table.concat(harvest, " "))Программа выводит:
45 30 18 12 7Условие «a идёт первым, если он больше» даёт список от наибольшего к наименьшему. Функция анонимная и записана прямо в вызове, как в предыдущем упражнении, поэтому end) закрывает и функцию, и вызов. Если один и тот же порядок нужен в нескольких местах, дайте функции имя и передавайте это имя: table.sort(harvest, biggerFirst).
Функция может сравнивать всё, что можно вычислить по двум элементам. Эта сортирует названия культур, начиная с самого короткого (названия здесь английские: оператор «#» считает байты, а русская буква занимает два байта):
local crops = {"wheat", "pumpkin", "corn", "carrot", "tomato", "potato"}
table.sort(crops, function(a, b)
return #a < #b
end)
print(table.concat(crops, " "))Программа выводит:
corn wheat tomato carrot potato pumpkinПосмотрите на три названия из 6 букв: tomato carrot potato. Они стоят не в исходном порядке и не по алфавиту. Когда функция говорит, что ни один из двух элементов не должен идти первым, table.sort может поставить их в любом порядке. Если порядок таких элементов важен, добавьте для них второе правило, например алфавитный порядок для названий одинаковой длины:
local crops = {"wheat", "pumpkin", "corn", "carrot", "tomato", "potato"}
table.sort(crops, function(a, b)
if #a ~= #b then
return #a < #b
end
return a < b
end)
print(table.concat(crops, " "))Программа выводит:
corn wheat carrot potato tomato pumpkinЕсли длины разные, решает первый return: по длине. Только при одинаковой длине функция доходит до второго return, который сравнивает сами строки.
Одно правило для функций сравнения: для двух равных элементов функция должна возвращать false, потому что «a стоит перед b» не может быть верно в обе стороны. С >= вместо > каждое из двух равных чисел стояло бы перед другим, и table.sort может завершиться ошибкой:
local eggs = {5, 3, 5, 1}
table.sort(eggs, function(a, b)
return a >= b
end)
print(table.concat(eggs, " "))Программа завершается с ошибкой:
main.lua:2: invalid order function for sortingСообщение говорит, что функция сравнения недопустима. Поэтому сравнивайте с помощью < или >, но никогда — с помощью <= или >=.
Задание
- 1
В списке
weightsуказан вес каждой корзины урожая в килограммах. Отсортируйте его от самой тяжёлой корзины к самой лёгкой и выведите, соединив элементы пробелами. Программа выводит23 17 14 9 5. - 2
Отсортируйте
cropsот самого длинного названия к самому короткому, а названия одинаковой длины — по алфавиту. Выведите их через пробел:strawberry pumpkin carrot potato tomato wheat corn - 3
Грядки Эммы расположены вдоль дорожки, а числа в
plots— это их позиции. Колодец находится в позицииwell. Эмма носит воду вёдрами, поэтому хочет сначала поливать грядки, ближайшие к колодцу. Отсортируйтеplotsпо расстоянию от колодца, которое равноmath.abs(plot - well). При одинаковом расстоянии первой идёт меньшая позиция. Выведите результат через пробел:8 12 6 14 3 18