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

Lua 迭代器

Un itérateur (iterator) est un objet qui peut être utilisé pour parcourir des éléments partiels ou complets des conteneurs de bibliothèque standard, chaque objet itérateur représente une adresse déterminée dans le conteneur.

En Lua, l'itérateur est une structure de type pointeur qui permet de parcourir chaque élément de l'ensemble.

L'itérateur générique

L'itérateur générique conserve la fonction d'itération à l'intérieur, en réalité il conserve trois valeurs : la fonction d'itération, la constante de statut, et la variable de contrôle.

L'itérateur générique fournit les clés de l'ensemble/Format syntaxique correct pour value :

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

Dans le code ci-dessus, k et v sont des listes de variables ; pairs(t) est une liste d'expressions.

Voyez l'exemple suivant:

array = {"Google", "w}3codebox}
for key, value in ipairs(array) 
do
   print(key, value)
end

Le résultat de l'exécution du code précédent est :

1  Google
2  w3codebox

Dans l'exemple précédent, nous avons utilisé la fonction d'itération ipairs fournie par défaut en Lua.

Voici comment le for générique s'exécute :

  • Tout d'abord, initialisation, calculez la valeur de l'expression après in, l'expression doit retourner les trois valeurs nécessaires au for générique : la fonction d'itération, la constante d'état, et la variable de contrôle ; comme pour l'affectation multiple, si le nombre de résultats retournés par l'expression est insuffisant pour trois, ils seront automatiquement complétés par nil, et les parties en excès seront ignorées.

  • Deuxièmement, appelez la fonction d'itération avec les constantes d'état et les variables de contrôle en tant que paramètres (attention : pour la structure for, la constante d'état n'a pas d'utilité, elle ne sert qu'à obtenir sa valeur et à la transmettre à la fonction d'itération lors de l'initialisation).

  • Troisièmement, assignez la valeur retournée par la fonction d'itération à la liste de variables.

  • Quatrièmement, si la première valeur retournée est nil, la boucle se termine, sinon, exécutez le corps de la boucle.

  • Cinquièmement, retournez à l'étape deux pour appeler à nouveau la fonction d'itération

En Lua, nous utilisons souvent des fonctions pour décrire les itérateurs, chaque appel de cette fonction retourne l'élément suivant du ensemble. Les itérateurs de Lua incluent les deux types suivants :

  • Itérateur sans état

  • 多状态的迭代器

Itérateur sans état

Un itérateur sans état est un itérateur qui ne conserve aucune état, par conséquent, dans la boucle, nous pouvons utiliser un itérateur sans état pour éviter de créer des closures à un coût supplémentaire.

À chaque itération, la fonction d'itération est appelée avec les valeurs des deux variables (constante d'état et variable de contrôle) en tant que paramètres, un itérateur sans état utilise ces deux valeurs pour obtenir l'élément suivant.

Un exemple typique et simple d'itérateur sans état est ipairs, qui parcourt chaque élément du tableau.

Dans l'exemple suivant, nous avons utilisé une fonction simple pour réaliser l'itérateur, pour réaliser le carré du nombre n :

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

以上示例输出结果为:

1    1
2    4
3    9

L'état d'itération inclut la table parcourue (un état constant qui ne change pas pendant le processus de boucle) et l'indice de l'index courant (variable de contrôle), ipairs et les fonctions d'itération sont très simples, nous pouvons les réaliser ainsi en Lua :

function iter(a, i)
    i = i + 1
    local v = a[i]
    if v then
       return i, v
    end
end
 
function 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 元素。

多状态的迭代器

在许多情况下,迭代器需要保存多个状态信息,而不仅仅是简单的状态常量和控制变量。最简单的方法是使用闭包,另一种方法是将所有状态信息封装到 table 中,将 table 作为迭代器的状态常量。在这种情况下,可以将所有信息存储在 table 中,因此迭代函数通常不需要第二个参数。

以下示例我们创建了自己的迭代器:

array = {"Google", "w}3codebox}
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 内使用了闭包函数,实现了计算集合大小并输出各个元素。