What is the purpose of Line 2 In my code?
local table = {["First"] = 1, ["Second"] = 2, ["Third"] = 3}
for key, value in pairs(table) do
print(key)
end
Results-------------
First
Second
Third
What is the purpose of the line that says, "for key, value in pairs(table) do
Print(key) ?
I was wondering why it is essential.
As others have suggested in comments, you should really start by reading Programming in Lua. It will explain this and much more and is really a perfect place to start if you want to learn Lua.
Well then, as for what it does
Given a table like this
local tab = {first = 1, second = 2, third = 3}
the way you would usually iterate over all the key-value pairs in the table is like this
for key, value in pairs(tab) do
print(key .. ": " .. tostring(value))
end
This will loop over the three values in the table first = 1, second = 2, etc.
For each pair, key is set to the table key and value to its value. It then executes the code between do and end with those variables set.
So the example above will print the following:
first: 1
second: 2
third: 3
How does it work?
This is a bit more complex; Let's first of all see what pairs actually returns:
> t = {}
> print(pairs(t))
function: 68f18400 table: 0066b1d8 nil
The table it returns as its second argument is the same that we passed in.
The function that's returned by pairs is the next function, which, given a table and a key, returns the next key in the table, within an unknown order but without ever repeating keys.
You can easily confirm that on the command line.
> print(t)
table: 0066b1d8
> print(next)
function: 68f18400
Lua then turns the for loop into something like the following:
do
local f, state, iterator = next, tab, nil -- this is what's returned by pairs
while true do
local key, value = f(state, iterator)
if key == nil then break end
iterator = key
print(key, value) -- This is the body of our for loop
end
end
Related
Example:
mytable = {{id=100,wordform="One Hundread"},{id=200,wordform="Two Hundread"}}
I want to be able to access the row based on the id to do something like this:
mynum = 100
print ("The value is " .. mytable[mynum].wordform)
The main point here is I want to be able to set the index value so I can predictably retrieve the associated value later as I might do with a java hashmap.
Ideally your table should just use the ID as key:
local mytable = {[100] = {wordform = "One hundred"}, [200] = {wordform = "Two hundred"}}
print("The value is " .. mytable[100].wordform)
If your table is in list form, you can convert it to ID form rather easily:
local mytable_by_id = {}
for _, item in pairs(mytable) do mytable_by_id[item.id] = item end
Using the hash part of a Lua table is definitely preferable over looping over the list entries in linear time as Renshaw's answer suggests (the fact that it's hidden behind a metatable may hide the poor performance and trick the reader into believing a hash indexing operation is taking place here though).
Furthermore, that answer won't even work correctly, as the list part uses integer keys as well; IDs that are valid list part indices would possibly return the wrong element. You'd have to use a function instead of a metatable.
you can use metatable
setmetatable(mytable, {__index = function(tbl, id)
for _, item in pairs(tbl) do
if type(item) == "table" and item.id == id then
return item
end
end
end})
then
mynum = 100
print ("The value is " .. mytable[mynum].wordform) -- The value is One Hundread
I have following lua code that prints out the Mac Addresses of a device.
local sc = Command.Scan.create()
local devices = sc:scan()
local topicMac
local list = {}
for _,device in pairs(devices) do
print(device:getMACAddress())
list[device] = device:getMACAddress()
end
topicMac = list[0]
print(topicMac)
Since there are several addresses and they are listed in a table, I would like to save only the first one into the local variable "topicMac". I tried reaching that first value by adding the first index (0 or 1) in the array.
Why do I get nil as return?
The next keyword can be used as a variant function to retrieve the first index and value out of a table
local index, value = next(tab) -- returns the first index and value of a table
so in your case:
local _, topicMac = next(list)
"First" and "Second" depends on what we have as keys. To check it just use print():
for k,d in pairs(devices) do
print(k,' = ',d:getMACAddress())
end
If keys are numbers, you can decide which is "first". If keys are strings, you are still able to make an algorithm to determine the first item in the table:
local the_first = "some_default_key"
for k,d in pairs(devices) do
if k < the_first then -- or use custom function: if isGreater(the_first,k) then
the_first = k
end
end
topicMac = devices[the_first]:getMACAddress()
print(topicMac)
If keys are objects or functions, you can't compare them directly. So you have to pick just any first item:
for _,d in pairs(devices) do
topicMac = d:getMACAddress()
break
end
print(topicMac)
I want to make a table with specific names as keys and specific functions as values.
The key names represent commands that a user enters and if a key by that name exists, then the program should execute the code stored in that keys value.
So for example, we make a table with keys and functions inside the key value:
local t = {
["exit"] = quitGame,
...,
...
}
and we also have a function for example:
function quitGame()
print("bye bye")
os.exit()
end
so now we do:
userInput = io.read()
for i,v in pairs(t) do
if userInput == i then
--now here, how do I actually run the code that is stored in that key value (v)?
end
end
I hope you understand what I'm trying to do.
You have a table keyed by value. There's no need to loop to find the key you want. Just look it up directly. Then just call the value you get back.
local fun = t[userInput]
if fun then
fun()
end
In Lua, I can add an entry inside table with table.insert(tableName, XYZ). Is there a way I can add already existing table into table? I mean a directly call rather then traversing and add it.
Thanks
The insert in your example will work fine with whatever contents happen to be inside the XYZ variable (number, string, table, function, etc.).
That will not copy the table though it will insert the actual table. If you want to insert a copy of the table then you need to traverse it and insert the contents.
First: In general, you do not need table.insert to put new entries into tables.
A table in Lua is a collection of key-value pairs; entries can be made like this:
local t = {} --the table
local key= "name"
local value = "Charlie"
t[key] = value --make a new entry (replace an existing value at the same key!)
print(t.name) --> "Charlie"
Note that key can have any type (not just integer/string)!
Very often you will need tables for a simple special case of this: A sequence ("list", "array") of values. For Lua, this means you want a table where all the keys are consecutive integers, and contain all non-nil values. The table.insert function is intended for that special case: It allows you to insert a value at a certain position (or to append it at the end of the sequence if no position is specified):
local t = {"a", "b", "d"} --a sequence containing three strings (t[1] = "a", ...)
table.insert(t, "e") --append "e" to the sequence
table.insert(t, 3, "c") --insert "c" at index 3 (moving values at higher indices)
--print the whole sequence
for i=1,#t do
print(t[i])
end
If I understand what you mean correctly, you want to do this:
local t1 = {1, 2, 3}
local t2 = {4, 5, 6}
some_function(t1, t2)
-- t1 is now {1, 2, 3, 4, 5, 6}
There is indeed no way to do this without iterating t2. Here is a way to write some_function:
local some_function = function(t1, t2)
local n = #t1
for i=1,#t2 do t1[n+i] = t2[i] end
end
No, you must copy the second table's key/value pairs into the first table. Copying the existing values from the second table is what's known as a "shallow copy." The first table will reference the same objects as the second table.
This works under limited circumstances:
local n = #t1
for i=1,#t2 do t1[n+i] = t2[i] end
It does attempt to shift the t2 elements to just beyond the existing t1 elements. That could be a vital requirement but wasn't stated in the question.
It has a few of problems, though:
By using #t1 and #t2, it misses keys that aren't positive integers and can miss keys that are integers greater than a skipped integer key (i.e. never assigned or assigned nil).
It accesses the first table with an indexer so could invoke the __newindex metamethod. That probably wouldn't be desirable when only copying is wanted.
It accesses the second table with an indexer so could invoke the __index metamethod. That wouldn't be desirable when only copying is wanted.
You might think that ipairs could be used if only positive integer keys are wanted but it quits on the first nil value found so could miss even more than #t2 does.
Use pairs instead:
for key, value in pairs(t2) do
rawset( t1, key, value )
end
If you do want to avoid replacing existing t1 values when the keys match or otherwise map t2 keys in some way then that has to be defined in the requirements.
Bottom line: pairs is the way to get all the keys. It effectively does a rawget so it avoids invoking __index. rawset is the way to do a copy without invoking __newindex.
I can't get table entry index. I need it to remove an item from table.
I use table.insert to add entries to table.
Another question: why Lua doesn't have "overload" to function table.remove so one can remove item by associative index?
Tables implement an unordered one to many relation between keys and values. In other words, any particular key (index) can only appear once in a table, but a value can appear multiple times.
If you know the key k, then t[k] = nil will remove both the key and the associated value from the table. However, this operation has no effect on any other keys or values in the table.
The table.insert and table.remove functions operate over the set of sequential integer keys beginning at 1, that are used by convention to implement arrays or lists. For that purpose, they manipulate other values in the list so as to keep the list from developing holes.
One way to find a key at which some value is found is to simply search the table. If this will be done more than once, then it is probably a good idea to build a second table that inverts the key/value pairs so that lookup by value is as fast as lookup by index.
A suitable implementation will depend on your assumptions and needs. Some samples are:
-- return the first integer index holding the value
function AnIndexOf(t,val)
for k,v in ipairs(t) do
if v == val then return k end
end
end
-- return any key holding the value
function AKeyOf(t,val)
for k,v in pairs(t) do
if v == val then return k end
end
end
-- return all keys holding the value
function AllKeysOf(t,val)
local s={}
for k,v in pairs(t) do
if v == val then s[#s+1] = k end
end
return s
end
-- invert a table so that each value is the key holding one key to that value
-- in the original table.
function Invert(t)
local i={}
for k,v in pairs(t) do
i[v] = k
end
return i
end
t[k]=nil removes from t the entry with key k.
For the second question, the answer is that tables can have individual metatables.