|
To add to the many excellent replies you have already received:
Traversing just the "non-sequence" entries is unfortunately not as
simple as traversing the hash part. A sequence may (at least in
principle - in practice a rehash would move it to the list part)
live entirely in the hash part. A sequence may live partially in
the list and partially in the hash part. Or ideally (and probably
the case most of the time, when care is taken to produce sequences
sequentially), a sequence may live just in the list part. The list
part need not contain a proper sequence though; it may have holes.
This means that implementing such a "kpairs" would not be as
efficient as traversing the hash part. Instead, you'd first have
to use ipairs to find the length of the sequence, and then do a
normal pairs traversal, filtering out those keys that are in the
sequence.
So really, there is unfortunately pretty much no way around
iterating the table twice (in the worst case at least).
Here's my attempt at such a proper "kpairs" implementation:
function kpairs(t) local n = 0 while t[n + 1] do n = n + 1 end local function knext(_, k) local nk, nv = next(t, k) if type(nk) == "number" and math.tointeger(nk) and nk >= 1 and nk <= n then return knext(nil, nk) end return nk, nv end return knext end for k, v in kpairs{1, 2, 3, nil, 4, a = 5, [true] = 6, [3.5] = 1, [0] = 2} do print(k, v) end
(A common misconception is that pairs always iterates a sequence
first and inorder. pairs does indeed start traversal in the list
part, which is iterated inorder, but as said above, sequences need
not live (entirely) in the list part. This is not guaranteed by
the reference manual however, and it doesn't always work in
practice either; you can construct tables that serve as
counterexamples, however rare they may be in practice.)
- Lars
This question might have come up earlier, but I have not seen it. Thus I dare to ask.
With ipairs() a table is walked through the array sequence in the table.With pairs() all elements are visited while traversing the table, the sequence as well as the records.However, sometimes I need to visit the record keys only, leaving the elements of the sequence out.Of course I can do:for k,v in pairs(t) doif not tonumber(k) then ... endend
But why isn't there a kpairs() for the record keys? I think it would make some programs easier, especially where the relevant pairs() function is passed to another function.
If I am wrong I will gladly hear it.
yours sincerelydr. Hans van der Meer