0Pricing
Lua Academy · Урок

Обобщённый for и break

Используйте обобщённый for с pairs/ipairs и управляйте ходом цикла с помощью break.

«Обобщённый for и break» — бесплатный урок Lua Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.

Протокол обобщённого цикла for

Обобщённый цикл for в Lua работает с функцией-итератором. Синтаксис имеет вид for vars in iter_func, state, init do. На каждой итерации Lua вызывает iter_func(state, lastVar) и присваивает возвращённые значения переменным vars. Цикл останавливается, когда первое возвращённое значение равно nil.

-- Manual use of next() iterator
local t = {a=1, b=2, c=3}
local key, val = next(t, nil)   -- first entry
while key ~= nil do
  print(key, val)
  key, val = next(t, key)       -- advance
end

pairs() для всех ключей

pairs(t) возвращает итератор, который перебирает все пары «ключ-значение» в таблице, включая строковые, целочисленные и смешанные ключи. Порядок перебора нецелочисленных ключей не определён (порядок хеширования). Перебираются и массивная, и хеш-часть таблицы.

local config = {
  host = "localhost",
  port = 8080,
  debug = true,
  [1] = "first",
}

for key, value in pairs(config) do
  print(key, value)
end
-- Prints all 4 entries in any order

ipairs() для ключей массива

ipairs(t) перебирает целочисленные ключи, начиная с 1, и останавливается на первом значении nil. Такой перебор безопасен, предсказуем и сохраняет порядок. Используйте ipairs для таблиц, похожих на массивы, когда важен порядок и нужно остановиться на первой пропущенной позиции.

local fruits = {"apple", "banana", "cherry"}

for i, fruit in ipairs(fruits) do
  print(i, fruit)
end
-- 1  apple
-- 2  banana
-- 3  cherry

-- stops at first nil
local t = {10, 20, nil, 40}
for i, v in ipairs(t) do
  print(i, v)  -- only 1,10 and 2,20
end

pairs и ipairs

Важно понимать, когда что использовать: ipairs предназначен для упорядоченных последовательных массивов, а pairs — для словарей и смешанных таблиц. ipairs останавливается на первой пропущенной позиции со значением nil, а pairs посещает каждый ненулевой ключ. Для обычных массивов вариант ipairs более идиоматичен.

local mixed = {10, 20, key="val", 30}

-- ipairs only sees array part in order
print("ipairs:")
for i, v in ipairs(mixed) do
  print(i, v)  -- 1:10, 2:20, 3:30
end

-- pairs sees everything
print("pairs:")
for k, v in pairs(mixed) do
  print(k, v)  -- 1:10, 2:20, 3:30, key:val
end

Пользовательский итератор с замыканием

Вы можете написать собственный итератор в виде замыкания. Функция-фабрика возвращает замыкание, хранящее состояние и перемещающее позицию при каждом вызове. Когда возвращать больше нечего, оно возвращает nil, чтобы остановить обобщённый цикл for.

local function range(from, to, step)
  step = step or 1
  local i = from - step
  return function()
    i = i + step
    if i <= to then return i end
  end
end

for n in range(1, 10, 2) do
  io.write(n .. " ")
end
print()  -- 1 3 5 7 9

string.gmatch как итератор

string.gmatch(s, pattern) возвращает итератор по всем совпадениям шаблона в строке s. Его часто используют для разделения строк, извлечения токенов или поиска всех вхождений шаблона.

local sentence = "the quick brown fox"

for word in string.gmatch(sentence, "%a+") do
  print(word)
end
-- the
-- quick
-- brown
-- fox

break в обобщённом цикле for

Обобщённый цикл for можно досрочно завершить с помощью break. Это полезно при поиске: перебирайте элементы, пока не найдёте совпадение, а затем выйдите из цикла. После выхода выполнение продолжается с инструкции после end.

local inventory = {
  {name="sword", damage=50},
  {name="shield", armor=30},
  {name="bow", damage=35},
}

local target = "shield"
for i, item in ipairs(inventory) do
  if item.name == target then
    print("Found at index", i)
    break
  end
end

Изменение таблиц во время перебора

Никогда не добавляйте и не удаляйте ключи таблицы во время перебора с помощью pairs() — поведение в этом случае не определено (какие-то изменения могут быть замечены, а другие пропущены). Если таблицу нужно изменить, соберите изменения во временный список и примените их после цикла.

local t = {a=1, b=2, c=3, d=4}
local toDelete = {}

-- Collect keys to delete
for k, v in pairs(t) do
  if v % 2 == 0 then
    toDelete[#toDelete+1] = k
  end
end

-- Delete after iteration
for _, k in ipairs(toDelete) do
  t[k] = nil
end
-- t = {a=1, c=3}

Шаблон перечисления

Если нужны и индекс, и значение, используйте ipairs, который предоставляет оба. Если нужны только значения, а индекс не важен, для индекса можно использовать _ — это общепринятое имя переменной, значение которой не используется.

local colors = {"red", "green", "blue"}

-- With index
for i, color in ipairs(colors) do
  print(i .. ": " .. color)
end

-- Ignore index with _
for _, color in ipairs(colors) do
  print(color)  -- just the values
end

Прямой вызов next()

next(t, key) — базовая функция перебора. Она возвращает следующую пару «ключ-значение» после key или nil, если элементов больше нет. Вызов next(t, nil) возвращает первую запись. С помощью next(t) ~= nil можно проверить, что таблица не пуста, — это быстрее, чем подсчитывать элементы.

local function isEmpty(t)
  return next(t) == nil
end

print(isEmpty({}))       -- true
print(isEmpty({1,2,3}))  -- false
print(isEmpty({a=1}))    -- false

Быстрая проверка

Какой итератор останавливается на первой пропущенной позиции со значением nil в таблице?

Итоги: обобщённый цикл for и break

Краткое содержание:

  • pairs(t) — все ключи, в любом порядке
  • ipairs(t) — целочисленные ключи от 1 до n, по порядку, с остановкой на nil
  • Пользовательские итераторы: возвращают замыкание, которое возвращает nil для остановки
  • break досрочно завершает цикл
  • Никогда не изменяйте таблицу во время перебора с pairs; собирайте изменения и применяйте их после
  • next(t) == nil — быстрая проверка на пустоту

Часто задаваемые вопросы

Урок «Обобщённый for и break» бесплатный?

Да — полный текст урока «Обобщённый for и break» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.

Чему я научусь в уроке «Обобщённый for и break»?

Используйте обобщённый for с pairs/ipairs и управляйте ходом цикла с помощью break. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Lua Academy?

Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Обобщённый for и break»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Lua Academy?

Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Инструкции if, elseif и else
  2. Циклы while и repeat-until
  3. Числовой цикл for
  4. Обобщённый for и break
← Назад к Lua Academy