问题
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.gsubwith 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 caseif val == str then. - When you do
f = truethe function still runs until it iterates through all items, so even if it finds something it just wastes your CPU time. You should usereturn 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 dotable.insert(a, b)iterateband 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