Lists of Records
One record describes one crop. For all of Emma's crops, put the records in a list. A table can hold other tables, so this is simply a list whose items are records:
local crops = {
{name = "Carrot", days = 3, price = 5},
{name = "Potato", days = 4, price = 8},
{name = "Pumpkin", days = 7, price = 20},
}
print(#crops)
print(crops[2].name)This prints:
3
PotatoRead crops[2].name from left to right: from crops, take the item with index 2 (the potato's record), and from it the field name. Everything you know about lists works here: #crops is the number of records, table.insert adds another one, and ipairs goes through them in order. In each round, the loop variable holds one whole record:
local crops = {
{name = "Carrot", days = 3, price = 5},
{name = "Potato", days = 4, price = 8},
{name = "Pumpkin", days = 7, price = 20},
}
for _, crop in ipairs(crops) do
print(crop.name .. ": " .. crop.price .. " coins")
endCarrot: 5 coins
Potato: 8 coins
Pumpkin: 20 coinsIt's a good habit to name the list in the plural and the loop variable in the singular: crops, crop.
Three patterns come up all the time with lists of records:
- Total: add up one field of every record, as in the lesson on lists.
- Filter: make a new list with only some of the records (or some of their values), using
ifandtable.insert. - Find: go through the list and return the first record that matches; when none does, return
nil.
local crops = {
{name = "Carrot", days = 3, price = 5},
{name = "Potato", days = 4, price = 8},
{name = "Pumpkin", days = 7, price = 20},
}
local function findCrop(list, name)
for _, crop in ipairs(list) do
if crop.name == name then
return crop
end
end
return nil
end
local function quickCrops(list)
local result = {}
for _, crop in ipairs(list) do
if crop.days <= 4 then
table.insert(result, crop.name)
end
end
return result
end
print(findCrop(crops, "Pumpkin").price)
print(findCrop(crops, "Corn"))
print(table.concat(quickCrops(crops), ", "))This prints:
20
nil
Carrot, PotatoThe return inside the loop ends the whole function as soon as the crop is found. The return nil at the end is reached only when no record matched. (A function without return returns nil too, but this way, it's clear what you meant.)
If you look up crops by name often, you can build a dictionary once: in a loop, byName[crop.name] = crop. Then byName["Pumpkin"] finds the record without a loop.
A list of records can be sorted with a comparison function, as in the lesson on functions: table.sort(crops, function(a, b) return a.price > b.price end) puts the most expensive crop first. Without the function, table.sort(crops) ends with attempt to compare two table values: Lua can't know which of two records should come first.
A typical mistake is to forget the index: crops.name is nil. The list itself has no name; only the records in it do. Pick a record first: crops[1].name.
Instructions
With ipairs, print every sale: the crop, the amount, the price of one piece and what the sale earned:
carrot: 6 x 5 = 30
pumpkin: 2 x 20 = 40
potato: 10 x 8 = 80
strawberry: 4 x 12 = 48
wheat: 9 x 3 = 27Below, add up what all the sales earned and print:
Total: 225 coinsWrite a function bigSales(list, minimum) that returns a new list with the names of the crops whose sale earned at least minimum coins. Print its result for 40 coins with table.concat:
pumpkin, potato, strawberryStart programming for free
7/10