About length fetch in lua
From the previous blog, we can see that lua5.2 does not have the getn function. The commonly used length fetch method is #
# Is worth noting.
The first thing to note is that lua has two parts: the array part and the hash table part. Basically, all operations are the first array and then the hash table.
Local test1 = {1, 2, 3, 4, 5}
Print (# test1)
Print result: 5
Local test1 = {1, 3, 5, 2, 4}
Print (# test1)
Print the result: 5 (okay .... Of course, like above, they are all used as values in the array ...)
Local test1 = {[1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5}
Print (# test1)
Print result: 5 (there is no array in the table, only the hash table)
Local test1 = {[1] = 1, [3] = 3, [4] = 4, [6] = 6, [2] = 2}
Print (# test1)
Print result: 6
For I = 1, # test1 do
Print (test1 [I])
End
If all are printed, 1 2 3 4 nil 6
The clearly written table has only five elements. How can it be changed to 6 .... The reason for this is to look at the lua source code implementation.
/*** Try to find a boundary in table `t'. A `boundary' is an integer index** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).*/int luaH_getn (Table *t) { unsigned int j = t->sizearray; if (j > 0 && ttisnil(&t->array[j - 1])) { /* there is a boundary in the array part: (binary) search for it */ unsigned int i = 0; while (j - i > 1) { unsigned int m = (i+j)/2; if (ttisnil(&t->array[m - 1])) j = m; else i = m; } return i; } /* else must find a boundary in hash part */ else if (isdummy(t->node)) /* hash part is empty? */ return j; /* that is easy... */ else return unbound_search(t, j);}
Or the first array. The array does not have the last hash part. Let's take a look at the length of the hash table.
static int unbound_search (Table *t, unsigned int j) { unsigned int i = j; /* i is zero or a present index */ j++; /* find `i' and `j' such that i is present and j is not */ while (!ttisnil(luaH_getint(t, j))) { i = j; j *= 2; if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ /* table was built with bad purposes: resort to linear search */ i = 1; while (!ttisnil(luaH_getint(t, i))) i++; return i - 1; } } /* now do a binary search between them */ while (j - i > 1) { unsigned int m = (i+j)/2; if (ttisnil(luaH_getint(t, m))) j = m; else i = m; } return i;}
J ++ ensures that j is the first value in the hash part. Starting from j, if the j position has a value, it will be doubled, check whether the values in the hash table can be obtained after double until no value is found. The value is in the range from I to j. Then, find the last nil found between I and j with a half-fold query. The front is its length. The error is omitted. LuaH_getint
Const TValue * luaH_getint (Table * t, int key). In its declaration, the second parameter is the key and the value is obtained through the key, in addition, if the Input key is a ++ operation, we can see that the length of the key used for searching must be an integer and must be continuous (not necessarily ). (Of course, this is an analysis without looking into the details to achieve a rough look .....)
Then verify:
Local test1 = {1, 3, [4] = 4, [6] = 6, [2] = 2}
Print (# test1)
Print result: 2
That is, in the source code above, the array part will be traversed first, and the array part will end, without traversing the hash table part.
Local test1 = {[4] = 4, [6] = 6, [2] = 2}
Print (# test1)
Print result: 0
The first digit after the array is j ++. If the value is nil, the I value is 0, and the j value is 1, the return value is 0.
Take a look at two items:
Local test1 = {[1] = 1, [2] = 2, [4] = 4, [6] = 6}
Print (# test1)
Local test1 = {[1] = 1, [2] = 2, [5] = 5, [6] = 6}
Print (# test1)
The two outputs are 6 and 2, and if the first one is printed as 1 2 3 4 nil 6, the difference between the two results will be displayed. If the difference is two, the difference will not work. why?
The algorithm in the source code above.
For example
Local test1 = {[1] = 1, [2] = 2, [3] = 3, [4] = 4, [6] = 6}
The first while loop ends, I = 4, j = 8, and you can use the following half to find the result (take the pen for details ...) Last I = 6
While local test1 = {[1] = 1, [2] = 2, [5] = 5, [6] = 6}
After the first while LOOP, I = 2, j = 4, after half-lookup, I = 2
Well, if you are not clear about this, you may encounter strange problems and waste a lot of time in actual operations ....
Last local test1 = {['a'] = 1, ['B'] = 2, ['C'] = 3}
Print (# test1)
Print result: the 0 key must be an integer before use.
Others take the array length form
If it is a string or other form, it is better to use the loop pairs form to retrieve it.
For more information about ipairs and pairs, see this blog .....