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
Potato

Read 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")
end
Carrot: 5 coins
Potato: 8 coins
Pumpkin: 20 coins

It'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 if and table.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, Potato

The 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 = 27

Below, add up what all the sales earned and print:

Total: 225 coins

Write 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, strawberry

Start programming for free

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

Or sign up with:

7/10