If you want to leave the original table unchanged, you could create a custom 'sort by value' iterator like this:
local function valueSort(a,b)
return a.value < b.value;
end
function sortByValue( tbl ) -- use as iterator
-- build new table to sort
local sorted = {};
for i,v in ipairs( tbl ) do sorted[i] = v end;
-- sort new table
table.sort( sorted, valueSort );
-- return iterator
return ipairs( sorted );
end
When sortByValue()
is called, it clones tbl
to a new sorted
table, and then sorts the sorted table. It then hands the sorted
table over to ipairs()
, and ipairs
outputs the iterator to be used by the for
loop.
To use:
for i,v in sortByValue( myTable ) do
print(v)
end
While this ensures your original table remains unaltered, it has the downside that each time you do an iteration the iterator has to clone myTable
to make a new sorted
table, and then table.sort
that sorted
table.
If performance is vital, you can greatly speed things up by 'caching' the work done by the sortByValue()
iterator. Updated code:
local resort, sorted = true;
local function valueSort(a,b)
return a.value < b.value;
end
function sortByValue( tbl ) -- use as iterator
if not sorted then -- rebuild sorted table
sorted = {};
for i,v in ipairs( tbl ) do sorted[i] = v end;
resort = true;
end
if resort then -- sort the 'sorted' table
table.sort( sorted, valueSort );
resort = false;
end
-- return iterator
return ipairs( sorted );
end
Each time you add or remove an element to/from myTable
set sorted = nil
. This lets the iterator know it needs to rebuild the sorted
table (and also re-sort it).
Each time you update a value
property within one of the nested tables, set resort = true
. This lets the iterator know it has to do a table.sort
.
Now, when you use the iterator, it will try and re-use the previous sorted results from the cached sorted
table.
If it can't find the sorted
table (eg. on first use of the iterator, or because you set sorted = nil
to force a rebuild) it will rebuild it. If it sees it needs to resort (eg. on first use, or if the sorted
table was rebuilt, or if you set resort = true
) then it will resort the sorted
table.
table.sort(your_table, function(a,b) return a.value < b.value end)