Function - table.indexOf(array,...)
- (R3) - Returns indexes of number/string/table/function in array.
@dave1707 I have been trying to work on the readability of my functions before posting them a little more so they are easier to go over.
Description:
This is another table extension which is inspired by the JavaScript indexOf function. It will traverse a table and return the index or indexes of occurance of a particular number, string, function, or table. Bear in mind however that a function or table in Lua is only equal to itself. This function does not compare tables or functions, but instead will return nil if the table or function is not a pointer to the same one. (I am working on a comparison function however for this purpose) The function supports a variable number of arguments and will return either the index of occurrence or nil if not found for all arguments.
Note: This function is only intended for arrays, not tables. If a table is attempted to be searched, it will in most cases throw an error, though some may not and may return unexpected results, so try not to use the function for tables. If you want to make the function catch all non arrays then you can use the conditionals from the table.getS() above, but I didn’t include them in this function so that it could be standalone for those who wanted to use it but not implement the other.
Note 2 : Unlike some other implementations of indexOf, this function can also jump over holes in an array, so having non sequential arrays is not an issue as long as they have numerical keys. Technically it could be easily changed to also return keys of a keyed table with non numerical keys, but I wanted to keep the function true to its original purpose, and it would have to be changed somewhat to support searching for sub tables.
Usage Examples:
local A = {} local B = function() end
Table = {12,20,"Foo","Bar",nil,"Foo",A,B}
The first example shows how the indexOf can be used to search for a single value in an array. When there is only two arguments, the function will return all instances of occurrence in sequential order.
table.indexOf(Table,"Foo")
- Returns 3,6
You can also specify multiple elements in a single call and the function will return the first instance of occurrence for each argument
table.indexOf(Table,"Foo","Bar",12,20)
- Returns 3,4,1,2
Entries that are passed to the function that are not found will return nil for each occurrence.
table.indexOf(Table,"Foo","FooBar","Bar","Bear")
- Returns 3,nil,4,nil
table.indexOf(Table,"Hello","World")
- Returns nil,nil
Entries passed to the function that are nil will also return nil. Generally you wouldn’t search for nil explicitly in an array (though that will technically work as well), but is more likely to happen when a variable is not defined and you attempt to search for it.
table.indexOf(Table,"Foo",nil)
- Returns 3,nil
table.indexOf(Table,nil,"Bar",nil,"Foo",nil)
- Returns nil,4,nil,3,nil
table.indexOf(Table,nil,nil)
- Returns nil,nil
You will always get a return for every argument that you pass to the function. While it may seem repetitious to have an output like the last above, while it doesn’t matter for variable assignment, it can be useful if you are doing things like printing results on the screen or for debug purposes.
Finally, you can also search for tables and functions within an array, but in Lua, tables and functions are only equal to themselves or nil, so in order to search for one you need to search for a pointer to the table or function which would generally be some kind of variable. (or if the function is global then you can just search for the function name)
table.indexOf(Table,A,B)
- Returns 7,8
table.indexOf(Table,{})
- Returns nil
Even though the last example above attempts to search for a table that is the same as the one which is in the array, the return is nil because even though it’s values are the same, it is not the same table.
Here is the actual function:
-- Returns Index of Arguments in Array
function table.indexOf(array,...)
if type(array) ~= "table" or #array == 0 and array ~= {} then
error("Invalid argument no.1 to indexOf array expected, was "..type(array))
else local Vals,Indexes,Pos = {...},{},1
local function Check(...) -- Checks if Arguments are nil
for i = Pos,arg.n do if Vals[i] == nil then Pos = Pos + 1
elseif Vals[i] then break end end end Check(...)
for _,entry in pairs(Vals) do
for index,val in pairs(array) do
if entry == val and type(index) == "number" then
table.insert(Indexes,Pos,index) Pos = Pos + 1 Check(...)
if #Vals ~= 1 then break end
elseif index == #array then
if #Vals ~= 1 then Pos = Pos + 1 Check(...)
elseif #Vals == 1 and Pos == 1 then Pos = Pos + 1
end end end end
return unpack(Indexes,1,Pos - 1)
end end
Change log:
Update R2 - September 23, 2013 - Revision no.1 had an undefined variable ‘Length’ that would always evaluate to nil and prevent the return of multiple indexes if there were only two arguments to the function. Currently the only bug I am aware of is if you search for a table in the array that is not found and then search for an explicit nil (An argument that is undefined) the order of returns will be different than the input order. (The nil will be put as the last return instead of its sequential order) I’m working at fixing this, but until I do, try not to do this until I can resolve the error or you will receive unexpected returns.
Update R3 - Fully Functional. I figured out that I just was not performing a check for nil arguments after a value was not found, so it wouldn’t return another value until the next non explicit nil element was searched. This didn’t only affect tables, I just happened to catch it with that. Now it will as I said before truly return a numerical index or nil for every argument passed to it.