Sorting with a Function

In the lesson on lists, table.sort(t) sorted numbers from the smallest and texts by their character codes. That's because table.sort compares the items with <. To sort them any other way, give it a second argument: a function that compares two items. table.sort calls it again and again with two items, a and b, and the function returns true when a should come before b:

local harvest = {12, 30, 7, 45, 18}
table.sort(harvest, function(a, b)
    return a > b
end)
print(table.concat(harvest, " "))

This prints:

45 30 18 12 7

“a comes first when it's bigger” gives a list from the largest to the smallest. The function is anonymous and written right in the call, as in the previous exercise, so end) closes both the function and the call. If you need the same order in several places, give the function a name and pass the name: table.sort(harvest, biggerFirst).

The function can compare anything it can work out from the two items. This one sorts crop names from the shortest:

local crops = {"wheat", "pumpkin", "corn", "carrot", "tomato", "potato"}
table.sort(crops, function(a, b)
    return #a < #b
end)
print(table.concat(crops, " "))

This prints:

corn wheat tomato carrot potato pumpkin

Look at the three names with 6 letters: tomato carrot potato. They're neither in their original order nor in alphabetical order. When the function says that neither of two items comes first, table.sort may put them in any order. When the order of such items matters to you, add a second rule for them, for example alphabetical order for names of the same length:

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, " "))

This prints:

corn wheat carrot potato tomato pumpkin

When the lengths differ, the first return decides by length. Only for the same length does the function get to the second return, which compares the texts themselves.

One rule for comparison functions: for two equal items, the function must return false, because “a comes before b” can't be true both ways. With >= instead of >, each of two equal numbers would come before the other, and table.sort may end with an error:

local eggs = {5, 3, 5, 1}
table.sort(eggs, function(a, b)
    return a >= b
end)
print(table.concat(eggs, " "))

The program ends with an error:

main.lua:2: invalid order function for sorting

The message says that the comparison function isn't valid. So compare with < or >, never with <= or >=.

Instructions

The list weights holds the weight of each basket of the harvest in kilograms. Sort it from the heaviest to the lightest, and print it joined with spaces. The program prints 23 17 14 9 5.

Sort crops from the longest name to the shortest, and names of the same length alphabetically. Print them joined with spaces:

strawberry pumpkin carrot potato tomato wheat corn

Emma's plots lie along a path, and the numbers in plots are their positions. The well is at the position well. Emma carries the water in buckets, so she wants to water the plots closest to the well first. Sort plots by their distance from the well, which is math.abs(plot - well). For the same distance, the smaller position comes first. Print the result joined with spaces:

8 12 6 14 3 18

Start programming for free

By signing up, you agree to the Terms of Service and Privacy Policy.

Or sign up with:

8/11