English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Итератор(iterator) является объектом, который можно использовать для遍ения части или всех элементов контейнера стандартной библиотеки шаблонов, каждый объект итератора представляет определенный адрес в контейнере.
В Lua итератор является структурой, поддерживающей тип указателя, которая может遍ировать каждым элементом набора.
Генерический for-迭代атор сохраняет внутреннюю функцию итерации, фактически он сохраняет три значения: функцию итерации, константный статус и переменную управления.
Генерический for-迭代атор предоставляет пары ключ/значение набора, формат синтаксиса следующий:
for k, v in pairs(t) do print(k, v) end
В данном коде k, v являются списком переменных; pairs(t) является списком выражений.
Смотрите следующий пример:
array = {"Google", "w3codebox"} for key,value in ipairs(array) do print(key, value) end
Результат выполнения кода:
1 Google 2 w3codebox
В предыдущем примере мы использовали стандартную функцию итерации Lua ipairs.
Теперь посмотрим, как выполняется универсальный for:
Первый, инициализация, вычислим значение выражения после in, выражение должно вернуть три значения, необходимые для универсального for: функция итерации, константа состояния, контрольная переменная; как и в случае с множественной присваиванием, если выражение возвращает меньше трех значений, они автоматически дополняются nil, избыточные значения игнорируются.
Второй, вызовем функцию итерации с константой состояния и контрольной переменной в качестве параметров (обратите внимание: для структуры for константа состояния не имеет значения, она используется только для инициализации и передается функции итерации).
Третий, присвоим значения, возвращенные функцией итерации, переменным.
Четвертый, если первый возвращаемый значением nil, цикл заканчивается,否则 выполняется тело цикла.
Пятый, вернемся ко第二步 и вызовем функцию итерации снова
В Lua мы часто используем функции для описания итераторов, и каждый раз, когда мы вызываем эту функцию, она возвращает следующий элемент набора. Итераторы Lua включают следующие два типа:
Без состояния итератор
Итераторы с несколькими состояниями
Без��态ный итератор - это итератор, который не сохраняет никакое состояние, поэтому в цикле мы можем использовать без��态ный итератор, чтобы избежать дополнительных затрат на создание closures.
В каждой итерации функция итерации вызывается с двумя переменными (константа состояния и контрольная переменная) в качестве параметров, без��态ный итератор использует только эти две переменные для получения следующего элемента.
Типичным простым примером такого без��态ного итератора является ipairs, который проходим по каждому элементу массива.
В следующем примере мы используем простую функцию для реализации итератора, чтобы получить квадрат числа n:
функция square(iteratorMaxCount, currentNumber) если currentNumber < iteratorMaxCount then currentNumber = currentNumber + 1 возврат currentNumber, currentNumber * currentNumber end end for i, n in square, 3, 0 do print(i, n) end
Приведенные выше примеры выводят результат:
1 1 2 4 3 9
Состояние итерации включает таблицу, которая проходима (состояние константы, которое не изменяется в процессе итерации) и текущий индекс индекса (контрольная переменная), функции ipairs и итерации очень просты, и мы можем реализовать это в Lua следующим образом:
функция iter(a, i) i = i + 1 локальная переменная v = a[i] если v то возврат i, v end end функция ipairs(a) return iter, a, 0 end
Когда Lua вызывает ipairs(a) для начала цикла, он получает три значения: функцию итерации iter, константу состояния a и начальное значение переменной контроля 0; затем Lua вызывает iter(a,0) и возвращает 1, a[1] (если a[1] не nil);第二次 итерация вызывает iter(a,1) и возвращает 2, a[2]……до первого nil элемента.
Во многих случаях итератор должен сохранять несколько состояний, а не просто константы состояния и контролируемые переменные. Самый простой способ - это использование функции-закрытия,还有一种 способ - это封装 всех состояний в таблицу, таблицу как состояние константы итератора, так как в этом случае все данные могут быть сохранены в таблице, поэтому функция итерации обычно не требует второго параметра.
В следующем примере мы создаем свой собственный итератор:
array = {"Google", "w3codebox"} function elementIterator(collection) local index = 0 local count = #collection -- Функция-закрытие return function () index = index + 1 if index <= count then -- Возвращает текущий элемент итератора return collection[index] end end end for element in elementIterator(array) do print(element) end
Приведенные выше примеры выводят результат:
Google w3codebox
В приведенных выше примерах мы можем видеть, что в elementIterator используется функция-закрытие, которая реализует вычисление размера集合 и вывод всех элементов.