Lua learning (12)--Lua iterator

An iterator is an object that can be used to traverse some or all of the elements in a standard template library container. Each iterator object represents a certain address in the container.
In Lua, an iterator is a type that supports pointers. A structure that iterates over each element of the collection.

Generic for iterator

The generic for saves the iteration function inside itself, in fact it saves three values: the iteration function, the state constant, and the control variable.
The generic for iterator provides a set of key/value pairs, the syntax is as follows:

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

In the above code, k, v is a list of variables; pairs(t) is a list of expressions. Check out the examples below:

array = {"Lua", "Tutorial"}

for key,value in ipairs(array) 
do
   print(key, value)
end

The output of the above code execution is:

1  Lua
2  Tutorial

In the above example, we used the iterative function ipairs provided by Lua by default.
Let's take a look at the execution process of the generic for:

  • First, initialize, calculate the value of the expression after in, the expression should return
    the three values ​​required by the generic for: iterative function, state constant, control variable; like multi-value assignment, if the number of results returned by the expression is less than three Each will be automatically filled with nil, and the extra part will be ignored.
  • Second, call the iterative function with the state constant and the control variable as parameters (note: for the for structure, the state constant is not useful, just get its value at initialization and pass it to the iterative function).
  • Third, assign the value returned by the iteration function to the list of variables.
  • Fourth, if the first value returned is nil, the loop ends, otherwise the loop body is executed.
  • Fifth, go back to the second step and call the iterative function again

In Lua we often describe iterators as functions that return the next element of the collection each time the function is called. Lua's iterators include the following two types:

  • stateless iterator
  • multi-state iterator

stateless iterator

A stateless iterator is an iterator that does not retain any state, so we can use stateless iterators in loops to avoid the extra cost of creating closures.
Each iteration, the iteration function is called with the values ​​of two variables (state constant and control variable) as arguments, and a stateless iterator uses only these two values ​​to get the next element.
A typical simple example of such stateless iterators are ipairs, which iterate over each element of an array.
In the following example we use a simple function to implement an iterator to square a number 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

The output of the above example is:

1    1
2    4
3    9

The iterative state includes the traversed table (state constant that will not change during the loop) and the current index subscript (control variable), ipairs and iterative functions are very simple, we can achieve this in 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

When Lua calls ipairs(a) to start the loop, it gets three values: the iteration function iter, the state constant a, and the initial value of the control variable 0; then Lua calls iter(a,0) to return 1, a[1] (unless a [1]=nil); the second iteration calls iter(a,1) to return 2,a[2]...until the first nil element.

multi-state iterator

In many cases, iterators need to store multiple state information instead of simple state constants and control variables. The easiest way is to use closures. Another way is to encapsulate all state information into a table and use the table as an iterator. The state constant of the controller, because in this case all the information can be stored in the table, so the iterator function usually does not need the second parameter.
The following example we create our own iterator:

array = {"Lua", "Tutorial"}

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

The output of the above example is:

Lua
Tutorial

The difference between pairs and ipairs

Same: Both can traverse collections (tables, arrays)
Different:
(1)

  • pairs: can traverse all the keys in the table can return nil
  • ipairs: cannot return nil, if it encounters nil, it will exit
    . That is to say, ipairs can only follow the order of 1, 2, 3, 4.... If there is an index jump in the middle, it will interrupt the output, and the first If the index is not 1, nothing is output.

(2)

  • ipairs just iterates over the values.
  • pairs can iterate over all elements of a collection. That is, pairs can traverse all keys in the collection, and can return nil in addition to the iterator itself and the traversal table itself.
local tab= { 
[1] = "a", 
[3] = "b", 
[4] = "c" 
} 
for i,v in pairs(tab) do        -- 输出 "a" ,"b", "c"  ,
    print( tab[i] ) 
end 

for i,v in ipairs(tab) do    -- 输出 "a" ,k=2时断开 
    print( tab[i] ) 
end

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325575123&siteId=291194637