English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

迭代器Lua

El iterador (iterator) es un objeto que se puede usar para recorrer parte o todos los elementos de una colección de la biblioteca de plantillas estándar, cada objeto de iterador representa una dirección determinada en la colección.

En Lua, el iterador es una estructura de tipo puntero que permite recorrer cada elemento de la colección.

Iterador genérico

El iterador genérico guarda la función de iteración internamente, en realidad guarda tres valores: la función de iteración, el constante de estado, y la variable de control.

El iterador genérico proporciona la clave de la colección/Valor correcto, el formato de sintaxis es el siguiente:

for k, v in pairs(t) do
    print(k, v)
end

En el código anterior, k, v son listas de variables; pairs(t) es una lista de expresiones.

Verifique el siguiente ejemplo:

array = {"Google", "w3codebox"}
for key, value in ipairs(array) 
hacer
   print(key, value)
end

El resultado de la ejecución del código anterior es:

1  Google
2  w3codebox

En el ejemplo anterior, usamos la función de iteración ipairs proporcionada por Lua por defecto.

Veamos el proceso de ejecución del for genérico a continuación:

  • Primero, inicializar, calcular el valor de la expresión después de in, la expresión debe devolver tres valores necesarios para el for genérico: la función de iteración, el estado constante y la variable de control; al igual que en la asignación de múltiples valores, si la expresión devuelve un número insuficiente de resultados, se completa automáticamente con nil, y la parte en exceso se ignora.

  • Segundo, llamar a la función de iteración con los parámetros de estado constante y variable de control (nota: para la estructura for, el estado constante no tiene uso, solo se obtiene su valor al inicializar y se pasa a la función de iteración).

  • Tercero, asignar el valor devuelto por la función de iteración a una lista de variables.

  • Cuarto, si el primer valor devuelto por la función de iteración es nil, finaliza el ciclo, de lo contrario, ejecuta el cuerpo del ciclo.

  • Quinto, regresar al paso dos y llamar nuevamente a la función de iteración

En Lua, a menudo usamos funciones para describir iteradores, y cada vez que se llama a esta función, se devuelve el siguiente elemento de la colección. Los iteradores de Lua contienen los siguientes dos tipos:

  • Iterador sin estado

  • iterador de múltiples estados

Iterador sin estado

Un iterador sin estado es uno que no mantiene ningún estado, por lo que podemos utilizar un iterador sin estado en un bucle para evitar el costo adicional de crear closures.

En cada iteración, la función de iteración es llamada con dos variables (un valor constante de estado y una variable de control) como parámetros, y un iterador sin estado utiliza estos dos valores para obtener el siguiente elemento.

Un ejemplo típico y simple de iterador sin estado es ipairs, que recorre cada elemento del array.

A continuación, un ejemplo simple de función para implementar el iterador, que realiza la implementación de la potencia cuadrada del número n:

function square(iteratorMaxCount, currentNumber)
   if currentNumber < iteratorMaxCount
   entonces
      currentNumber = currentNumber+1
   return currentNumber, currentNumber*currentNumber
   end
end
for i, n in square,3,0
hacer
   print(i, n)
end

El resultado de la salida del ejemplo anterior es:

1    1
2    4
3    9

El estado de la iteración incluye la tabla que se está recorriendo (un estado constante que no cambia durante el proceso de iteración) y el índice de subíndice actual (variable de control), las funciones ipairs y de iteración son muy simples, y podemos implementarlas así en Lua:

function iter(a, i)
    i = i + 1
    local v = a[i]
    if v then
       return i, v
    end
end
 
function ipairs(a)
    devolver iter, a, 0
end

Cuando Lua llama a ipairs(a) para comenzar el ciclo, obtiene tres valores: la función de iteración iter, la constante de estado a, y el valor inicial del variable de control 0; luego Lua llama a iter(a,0) para devolver 1, a[1](a menos que a[1=nil);la segunda llamada de iteración a iter(a,1) devolver 2, a[2……hasta el primer elemento nil.

iterador de múltiples estados

En muchos casos, el iterador necesita guardar múltiples información de estado en lugar de simples constantes de estado y variables de control, el método más simple es usar una función de clausura, y hay otro método que es encapsular toda la información de estado en una tabla, y usar la tabla como constante de estado del iterador, porque en este caso se puede guardar toda la información dentro de la tabla, por lo que la función de iteración generalmente no necesita un segundo parámetro.

En los siguientes ejemplos creamos nuestro propio iterador:

array = {"Google", "w3codebox"}
function elementIterator(colección)
   local index = 0
   local count = #colección
   -- función de clausura
   devolver función ()
      index = index + 1
      si index <= count
      entonces
         --  devolver el elemento actual del iterador
         devolver colección[index]
      end
   end
end
para elemento en elementoIterator(array)
hacer
   imprimir(element)
end

El resultado de la salida del ejemplo anterior es:

Google
w3codebox

En los ejemplos anteriores, podemos ver que el elementoIterator utiliza una función de clausura para calcular el tamaño de la colección y mostrar cada elemento.