Lua - Most resource efficient way to compare a variable with a fixed list of values

So I have a variable, let's call it "ID". I need to check this value against a fixed number of values. An identifier can of course only match one of the values, so there is no problem stopping the first match value as none of the others will match. There is also the possibility that the variable does not match any of the given values. My question is what is the most resource efficient way to do this? I can think of two simple ways to solve the problem. Since I know the values ​​during programming, I can set a conditional expression using "or" that simply checks each value, for example:

if (ID == "1" or ID == "16" or ID == "58") then
    --do something--
end

      

The problem is that this is quite verbose and tedious to write. Another option includes a foreach loop where I pre-define the table.

values = {"1", "16", "58"}
for _, value in ipairs(values) do
    if(ID == value) then
        return true
    end
end

      

The upside of this is reusability, which is good since I will need to do this exact check with a different set of values ​​at least 10 times, but I suspect this is more resource intensive.

Any help would be greatly appreciated.

+3


source to share


1 answer


Tables can be used as sets:

interesting = {
   ["1"] = true, ["16"] = true, ["58"] = true
}

if interesting[ID] then
   -- ...
end

      

While it consumes more memory (80 bytes per empty table plus 32 bytes (IIRC, on x86_64) per write (when rounding the number of records to the next cardinality by 2) versus 16 bytes per comparison plus memory for the value you are comparing) the chain of comparisons happens in C and is therefore faster than chaining comparisons like a sequence of Lua instructions (at least when things get bigger).

For a small number of values, it doesn't really matter. (If you are CPU bound and this is very important in your case, measure in the context of your program and see which performs better. Don't put too much weight on micro tests with this - cache behavior in particular can have funny effects here .)



For a lot of comparisons, this is the correct approach. It is also more flexible than if

- then

- chains else

. (You can change the situation at runtime without reloading your code.)

Also note that the value you use to bind an item in a set doesn't really matter, so a relatively common idiom (especially for handling input) is to place an action as a function in a table:

keybindings = {
   left = function()  Player:move_left( )  end,
   right = function()  Player:move_right( )  end,
   up = function()  Player:jump( )  end,
   -- ...
}

function onKey( k )
   local action = keybindings[k]
   if action then  action( )  end
end

      

While this is of course slower than direct comparison and inline code, speed is practically irrelevant here (it usually happens much less frequently than ~ 100 times per second) and flexibility is of great value.

+8


source







All Articles