Check if Table contains a value in lua

[亡魂溺海] 提交于 2020-12-12 12:14:30

问题


I am looking for a method to see if the value is in array (table)

The example table has 3 entries, each entry containing a table with multiple entries

Say I am checking if 'apple' is in 'data'

  data = {
{"alpha","bravo","charlie","delta"},
{"apple","kiwi","banana","pear"},
{"carrot","brocoli","cabage","potatoe"}
}

This is the code I have, a recursive query. The problem is the function breaks somewhere as it drops the positive value

local function hasValue(tbl, str)

local f = false

    for ind, val in pairs(tbl) do
    
            if type(val) == "table" then
        
                hasValue(val, str)

            else
                    if type(val) == "string" then
         
                        if string.gsub(val, '^%s*(.-)%s*$', '%1') == string.gsub(str, '^%s*(.-)%s*$', '%1') then 
                            f = true
                        end

                    end
            end
    end

return f end

Any help on this or alternative method would be greatly appreciated.

Here is the full test file


回答1:


local function hasValue( tbl, str )
    local f = false
    for i = 1, #tbl do
        if type( tbl[i] ) == "table" then
            f = hasValue( tbl[i], str )  --  return value from recursion
            if f then break end  --  if it returned true, break out of loop
        elseif tbl[i] == str then
            return true
        end
    end
    return f
end

print( hasValue( data, 'apple' ) )
print( hasValue( data, 'dog' ) )

true
false




回答2:


Help:

  • You use string.gsub with a pattern that matches the whole string without trailing spaces. In your example you don't have trailing spaces at all, so it's a pointless function call and comparison. You should do direct string comparison in this case if val == str then.
  • When you do f = true the function still runs until it iterates through all items, so even if it finds something it just wastes your CPU time. You should use return true, because it found the item, no needs to contiunue.

Solution 1:

  • Best solution is to have a table lookup for all items (set-list). Create a table lookup = {}, and before/after you do table.insert(a, b) iterate b and add all its items into lookup table.
for k, v in ipairs(b) do
    lookup[v] = true
end

This puts values from b as keys in lookup, value true is just an indicator we have this key. Later on if you want to know if you have this item you just do print("Has brocoli:", lookup["brocoli"])

Solution 2:

  • This solution is slower but doesn't require to use additional tables. Just a fixed version of hasValue.
function hasValue(tbl, value)
    for k, v in ipairs(tbl) do -- iterate table (for sequential tables only)
        if v == value or (type(v) == "table" and hasValue(v, value)) then -- Compare value from the table directly with the value we are looking for, otherwise if the value is table, check its content for this value.
            return true -- Found in this or nested table
        end
    end
    return false -- Not found
end

Note: this function won't work with non-sequential arrays. It will work for your code.




回答3:


Thanks for the answer @codeflush.dev

local function hasValue(tbl, str)

local f = false

    for ind, val in pairs(tbl) do
    
            if type(val) == "table" then
        
                f = hasValue(val, str)

            else
                    if type(val) == "string" then
         
                        if string.gsub(val, '^%s*(.-)%s*$', '%1') == string.gsub(str, '^%s*(.-)%s*$', '%1') then 
                            f = true
                        end

                    end
            end
    end

return f end


来源:https://stackoverflow.com/questions/64717902/check-if-table-contains-a-value-in-lua

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!