I have stumbled upon a strange behavior of table.sort()
, in which the comparing function is invoked by passing the same array element in both parameters.
Consider the code below. I want to sort the array from highest to lowest value of the property v
and, in case they are equal (and since table.sort()
algorithm is not stable as of the docs), I want to sort them by the original indices of the elements.
-- The array to sort
local arr = {
{id="A", v = 1},
{id="B", v = 1},
{id="C", v = 0},
{id="D", v = 1},
{id="E", v = 1}
}
-- A map containing the original index of the elements in the array: element => originalIndex
local original_indices = {}
for index, elem in ipairs(arr) do
original_indices[elem] = index
end
-- Sort the array
table.sort(arr,
function(a, b)
assert(a ~= b, "Comparing the same element in the array!")
-- Compare the value
if a.v > b.v then
return true
elseif a.v < b.v then
return false
end
-- Values are equal. Compare original indices, which should always
-- decide the final order.
local ia = original_indices[a]
local ib = original_indices[b]
if ia < ib then
return true
elseif ia > ib then
return false
end
error("BUG! Comparing the same element in the array!")
end
)
The expected result should be:
{
{id="C", v = 0},
{id="A", v = 1},
{id="B", v = 1},
{id="D", v = 1},
{id="E", v = 1}
}
But, instead, I get an error because Lua is invoking the sorting function by passing the same element in both parameters, which should not.
Am I missing something? How can I get the expected result?
You can play around with the code here.