Списки записей
Одна запись описывает одну культуру. Чтобы описать все культуры Эммы, положите записи в список. Таблица может содержать другие таблицы, так что это просто список, элементы которого — записи:
local crops = {
{name = "Морковь", days = 3, price = 5},
{name = "Картофель", days = 4, price = 8},
{name = "Тыква", days = 7, price = 20},
}
print(#crops)
print(crops[2].name)Выведется:
3
КартофельЧитайте crops[2].name слева направо: из crops берётся элемент с индексом 2 (запись картофеля), а из неё — поле name. Всё, что вы знаете о списках, работает и здесь: #crops — число записей, table.insert добавляет ещё одну, а ipairs проходит по ним по порядку. На каждом круге переменная цикла хранит одну запись целиком:
local crops = {
{name = "Морковь", days = 3, price = 5},
{name = "Картофель", days = 4, price = 8},
{name = "Тыква", days = 7, price = 20},
}
for _, crop in ipairs(crops) do
print(crop.name .. ", цена: " .. crop.price)
endМорковь, цена: 5
Картофель, цена: 8
Тыква, цена: 20Хорошая привычка — называть список во множественном числе, а переменную цикла в единственном: crops, crop.
Со списками записей постоянно встречаются три приёма:
- Сумма: сложите одно поле каждой записи, как в уроке про списки.
- Фильтр: составьте новый список только из некоторых записей (или некоторых их значений) с помощью
ifиtable.insert. - Поиск: пройдите по списку и верните первую подходящую запись; если подходящей нет, верните
nil.
local crops = {
{name = "Морковь", days = 3, price = 5},
{name = "Картофель", days = 4, price = 8},
{name = "Тыква", 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, "Тыква").price)
print(findCrop(crops, "Кукуруза"))
print(table.concat(quickCrops(crops), ", "))Выведется:
20
nil
Морковь, Картофельreturn внутри цикла сразу завершает всю функцию, как только культура найдена. До return nil в конце программа доходит, только если ни одна запись не подошла. (Функция без return тоже возвращает nil, но так понятнее, что вы имели в виду.)
Если вы часто ищете культуры по названию, можно один раз построить словарь: в цикле byName[crop.name] = crop. Тогда byName["Тыква"] находит запись без цикла.
Список записей можно отсортировать функцией сравнения, как в уроке про функции: table.sort(crops, function(a, b) return a.price > b.price end) ставит первой самую дорогую культуру. Без функции table.sort(crops) заканчивается ошибкой attempt to compare two table values: Lua не может знать, какая из двух записей должна идти первой.
Типичная ошибка — забыть индекс: crops.name равно nil. У самого списка названия нет, оно есть только у записей в нём. Сначала выберите запись: crops[1].name.
Задание
- 1
С помощью
ipairsвыведите каждую продажу: культуру, количество, цену одной штуки и то, сколько продажа принесла: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 - 2
Ниже сложите выручку со всех продаж и выведите:
Итого: 225 монет - 3
Напишите функцию
bigSales(list, minimum), которая возвращает новый список с названиями культур, продажа которых принесла не меньшеminimumмонет. Выведите её результат для 40 монет черезtable.concat:pumpkin, potato, strawberry