Sorted Iteration Simple |
|
If one would need to access the table one could add a reference; holding the access functios in a metatable hides these from a normal traversal of the table but not from the lookup; still access is quite fast;
An implemention to view the table by sorted by values would be no problem if one doesn't delete any entries.
--[[ LUA 5.1 compatible Sorted Ordered Table keys added will also be stored in a metatable they can be called via for i,k in <this>:ipairs() do where k is they key of <this> sorted by fsort the table holding sorted keys is placed outside the metatable, so one cannot reach it except over the functions variable names inside __index shouldn't be added, if so you must change the variable names in the __index table to names that won't be used, or delete not used functions ]]-- function newT( t ) local mt,_korder = {},{} local fsort = function( a,b ) return tostring(a) < tostring(b) end local isSorted = true -- set methods mt.__index = { -- traversal of hidden values hidden = function() return pairs( mt.__index ) end, -- traversal of table ordered: returning index, key ipairs = function( self ) if not isSorted then table.sort( _korder,fsort ) isSorted = true end return ipairs( _korder ) end, -- traversal of table pairs = function( self ) return pairs( self ) end, -- traversal of table sorted: returning key,value spairs = function( self ) local i = 0 if not isSorted then table.sort( _korder,fsort ) isSorted = true end local function iter( self ) i = i + 1 local k = _korder[i] if k then return k,self[k] end end return iter,self end, -- to be able to delete entries we must write a delete function del = function( self,key ) if self[key] then for i,k in ipairs( _korder ) do if k == key then table.remove( _korder, i ) break end end self[key] = nil end end, } -- set new index handling mt.__newindex = function( self,k,v ) if not self[k] then table.insert( _korder, k ) isSorted = false end rawset( self,k,v ) end return setmetatable( t or {},mt ) end -- CHILLCODE™
t = newT() t["a"] = "1" t["ab"] = "2" t["abc"] = "3" t["abcd"] = "4" t["abcde"] = "5" t[1] = 6 t[2] = 7 t[3] = 8 t[4] = 9 t[5] = 10 print(">> t:pairs()") for k,v in t:pairs() do print( k,v ) end print(">> t:ipairs()") for i,k in t:ipairs() do print( i,k,t[k] ) end print(">> t:spairs()") for i,v in t:spairs() do print( i,v ) end print(">> t:del( 3 )") t:del( 3 ) print(">> t:del( \"abc\" )") t:del( "abc" ) print(">> t:spairs()") for i,v in t:spairs() do print( i,v ) end print(">> t.abc = 11") t.abc = 11 print(">> t:spairs()") for i,v in t:spairs() do print( i,v ) end
>> t:pairs() 1 6 2 7 3 8 4 9 a 1 ab 2 abcd 4 abcde 5 5 10 abc 3 >> t:ipairs() 1 1 6 2 2 7 3 3 8 4 4 9 5 5 10 6 a 1 7 ab 2 8 abc 3 9 abcd 4 10 abcde 5 >> t:spairs() 1 6 2 7 3 8 4 9 5 10 a 1 ab 2 abc 3 abcd 4 abcde 5 >> t:del( 3 ) >> t:del( "abc" ) >> t:spairs() 1 6 2 7 4 9 5 10 a 1 ab 2 abcd 4 abcde 5 >> t.abc = 11 >> t:spairs() 1 6 2 7 4 9 5 10 a 1 ab 2 abc 11 abcd 4 abcde 5