How do I access value in lua table? - lua

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)

Related

Lua how do you retrieve a table row by a table value?

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

How to get a Value's Key using index

How does one get the key from a table value using the index, like this;
local myTable = {
Mary = 1000,
Bob = 2000,
Fred = 3000}
local keyAtIndex1 = myTable[1] ??? --- should return "Mary"
local keyAtIndexTwo = myTable[2] ??? --- should return "Bob"
Is there a pre-built method or property?
I am currently doing this;
function tableGetKeyFromValue(_table, _value)
for k,v in pairs(_table) do
if v==_value then return k end
end
return nil
end
Is there a better way?
Keys in Lua tables do not have indices; they are indices. Keys in Lua tables are not ordered, so you cannot fetch them by some ordering.
Furthermore, there is no mechanism to fetch keys by their value. The map only goes one way: from keys to values. If you want to have a mapping from values to keys, you can build a separate table that stores that mapping easily enough.
However, nothing will exist to keep these two tables in sync with one another. That's fine if the table is more-or-less static.

Beginner Lua, Array

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

Lua execute something stored in tables key value

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

Potential problems with storing the second table of two dimensional arrays in the index

In the past I found myself using a table as index and value of
a table when the order was irrelevant.
Since every table returns a unique value they are save to use as
index and with that I already got all the information I want to
use later on in the program. Now I did not see any similar lua code
jet and didn't use it in a non test-program. So I'm worrying that I
might get some unforeseen/unexpected problems when using this method.
example:
a = {1,2,3,4,5} --some testing values
b = {2,nil,4,nil,1}
c = {3,nil,nil,nil,2}
d = {4,nil,1,nil,3}
e = {5,1,2,3,4}
tab = {a,b,c,d,e}
t = {}
for i, v in pairs(tab) do
t[v] = 0
end
for iv in pairs(t) do --is almost every time outputting it in a different order
print(iv[1],iv[2],iv[3],iv[4],iv[5]) --could be a list of data where you have to go through all of it anyway
end
io.read()
Now I can store some additional information in t[v] but if I don't have
any is there maybe some lua-type that is smaller?
Edit:
Does this go well with the use of weak-tables?
Note:
Standard 2d table: table[key1] = table
table[key1][key2] <-- contains stuff
this version: table[table] = anything but nil <-- not accessible over table[key1][key2]
key1[key2] <-- contains stuff
It's fine to use a table as a key in another table.
However, note that different tables will be different keys, even of the tables have the same contents.

Resources