Skip to content

Instantly share code, notes, and snippets.

@jirutka
Created November 24, 2015 00:33
Show Gist options
  • Save jirutka/89eb96b7469a7bfea020 to your computer and use it in GitHub Desktop.
Save jirutka/89eb96b7469a7bfea020 to your computer and use it in GitHub Desktop.
Implementation of Lua iterator “apairs”, a function that behaves opposite to “ipairs.”
--- Returns an iterator that behaves opposite to @{ipairs}, i.e. it iterates
-- over all key-value pairs that @{ipairs} does not. In other words, it skips
-- integer keys from 1 up to the first integer key absent from the table. The
-- order in which the keys are enumerated is not specified!
--
-- @tparam table tab The table to iterate.
-- @treturn function func An iterator.
-- @treturn table The given table.
local function apairs (tab)
-- #tab lies, so we must count it ourself...
local n = 1
for i, _ in ipairs(tab) do n = i end
local iter = function(t, i)
local val
repeat
i, val = next(t, i)
until i == nil or type(i) ~= 'number' or i > n
return i, val
end
return iter, tab, nil
end
return apairs
apairs = require 'apairs'
describe 'apairs', ->
apairs_t = (tab) ->
{ k, v for k, v in apairs(tab) }
context 'table with continuous integer keys only', ->
it 'returns empty table', ->
assert.same {}, apairs_t {'a', 'b', 'c'}
context 'table with string keys only', ->
it 'returns the same table', ->
input = {a: 1, b: 2, c: 3}
assert.same input, apairs_t(input)
context 'table with mixed continuous integer keys and string keys', ->
it 'returns entries with string keys only', ->
assert.same {x: 42, y: 55}, apairs_t {'a', x: 42, 'b', y: 55}
context 'table with integer keys starting with number greater than one', ->
it 'returns the same table', ->
input = {[3]: 'a', [4]: 'b', [6]: 'c'}
assert.same input, apairs_t input
context 'table with mixed continuous and non-continuous integer keys and string keys', ->
it 'returns entries with integer keys after gap and string keys', ->
assert.same {[4]: 'd', x: 42}, apairs_t {[1]: 'a', [2]: 'b', [4]: 'd', x: 42}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment