I would like to contruct a configuration file with the code :
But, my code is wrong, why ? the final line only print nil, nil, nil...
-- Define ten network interfaces
interfaces = {} -- Define an empty table
for n = 1, 10 do
interfaces[n] = {
device = "eth"..n,
address = "192.168.1."..n
}
end
for k, v in pairs(interfaces) do print(device,address) end
In the code below, the names device and address are resolved as global variables that are undefined. Hence the nils in the output.
for k, v in pairs(interfaces) do print(device,address) end
Try this instead:
for k, v in pairs(interfaces) do print(v.device,v.address) end
Since the order of pairs traversed by pairs is not defined, use ipairs if you need the list to be output in order.
Related
I have the following code which Roblox Developer and the Lua.org manual both say should work to remove an instance from the table so I can store as a local, but the local is only holding a nil value.
The table is there. It shows up on the print function. It just will not store to be useful in the app.
I have tried multiple versions of this code including going with just the pairs function, just the table.remove function, and going with and without the position for the table remove, and it all generates nil variable.
response = HttpService:GetAsync(mining)
data = HttpService:JSONDecode(response, Enum.HttpContentType.ApplicationJson)
local function tprint(t)
for k,v in pairs(t) do print(k,v) end
end
tprint(data)
local a = table.remove(data, 4)
local b = table.remove(data, 3)
local c = table.remove(data, 2)
local d = table.remove(data, 1)
The solution ended up being so simple, and yet so profound. I can now use this to link crypto, bank accounts, credit cards, and anything else I want directly into Roblox or any other lua based program.
a = (data["result"]["amount"])
Before I dig into the error you're seeing, first some background information.
Lua tables have two methods of indexing values: numerically, and by keys. Often times you will see these two different methods be used to describe the kind of data structure that uses it.
Arrays and lists are tables that use numeric keys to index information.
local arr = {}
arr[1] = "abc"
arr[2] = 123
arr[3] = true
-- print the length of the array
print(#arr) -- 3
-- print the contents of the array
for i, v in ipairs(arr) do
print(i, v)
-- 1 abc
-- 2 123
-- 3 true
end
On the other side of things, dictionaries and hash maps and associative arrays use keys to store information :
local dict = {}
dict["foo"] = "abc"
dict["bar"] = 123
dict["blah"] = true
dict["katz"] = { 1, 2, 3 }
-- print the number of numerical keys in the dictionary
print(#dict) -- 0
-- print the contents of the dictionary
for k, v in pairs(dict) do
print(k, v)
-- foo abc
-- bar 123
-- blah true
-- katz table
end
While lua allows a table to use both of these indexing methods simultaneously, it's important never to mix the two, as behaviors can get real funky when you do. When a table has keys, treat it like a dictionary. When a table has numerical indices, treat it like an array.
When you use HttpService to decode a JSON string into a table, it generates a dictionary that reflects the heirarchical structure of the original data.
The table library, which you call with table.insert() and table.remove() expects that the table you're working with is an array.
When your data is arranged like this :
local data = {}
data["Success"] = true
data["StatusCode"] = 200
data["StatusMessage"] = "Success"
data["Headers"] = {} -- a dictionary of headers
data["Body"] = {
result = {
amount = 1,
depositAddress = "blah",
},
} -- after HttpService:JSONDecode() is called...
And you tell it to remove a numbered index with table.remove(data, 4), it won't work because there's no data stored at index number 4. data is a dictionary, not an array.
Often, it is annoying to try to print out the contents of a table with multiple layers of data, especially JSON tables, as the pairs function will only index one level at a time. Thankfully, Roblox's print function and Output widget are smart enough to do this for you. You can simply print(data) and it will show you the full table in the output and allow you to inspect each level.
Then once you know how your data is structured you can step through it value by value.
local amount = data["Body"]["result"]["amount"]
-- or
local amount = data.Body.result.amount
local t={}
for i,v in pairs(game.Players:GetPlayers()) do
if v~=game.Players.LocalPlayer then
table.insert(t,v.Name)
end
end
if i do table.foreach(t,print) it also shows the index and it causes problems when i want to select a random player. The error usually tends to be something like "1 is not a valid member of workspace"
Your problem is not that table.insert adds an index, but that you use it instead of the value you want do use.
table.insert inserts an element to a list. If no index is given the value is added to the end of the list.
So there is no way to use table.insert without "inserting the index". Actually there is no way at all to add an element to a Lua table without providing a key. A Lua table is nothing but a set of key value pairs.
table.foreach calls a function for each key value pair.
You should rather use table.foreachi btw.
So table.foreachi(t, print) is equivalent to
print(1, t[1])
print(2, t[2])
...
If you just want to print the values:
for i,v in ipairs(t) do print(v) end
or for older Lua versions
table.foreachi(t, function(i,v) print(v) end)
Alternatively you run a numeric for loop:
for i = 1, t.n do print(t[i]) end
or
for i = 1, #t do print(t[i]) end
table.foreach(t,f) applies the function f to each key-value pair of t as is written. Also, since Lua 5.1 the function is deprecated.
If you want simply to print all values, do
for _, name in ipairs (t) do
print (name)
end
or
print (table.concat (t, ', '))
If you want a random name from t:
local random_name = t [math.random (#t)]
I have gone through many questions and Google results but couldn't find the solution.
I am trying to sort a table using table.sort function in Lua but I can't figure out how to use it.
I have a table that has keys as random numeric values. I want to sort them in ascending order. I have gone through the Lua wiki page also but table.sort only works with the table values.
t = { [223]="asd", [23]="fgh", [543]="hjk", [7]="qwe" }
I want it like:
t = { [7]="qwe", [23]="fgh", [223]="asd", [543]="hjk" }
You cannot set the order in which the elements are retrieved from the hash (which is what your table is) using pairs. You need to get the keys from that table, sort the keys as its own table, and then use those sorted keys to retrieve the values from your original table:
local t = { [223]="asd", [23]="fgh", [543]="hjk", [7]="qwe" }
local tkeys = {}
-- populate the table that holds the keys
for k in pairs(t) do table.insert(tkeys, k) end
-- sort the keys
table.sort(tkeys)
-- use the keys to retrieve the values in the sorted order
for _, k in ipairs(tkeys) do print(k, t[k]) end
This will print
7 qwe
23 fgh
223 asd
543 hjk
Another option would be to provide your own iterator instead of pairs to iterate the table in the order you need, but the sorting of the keys may be simple enough for your needs.
What was said by #lhf is true, your lua table holds its contents in whatever order the implementation finds feasible. However, if you want to print (or iterate over it) in a sorted manner, it is possible (so you can compare it element by element). To achieve this, you can do it in the following way
for key, value in orderedPairs(mytable) do
print(string.format("%s:%s", key, value))
end
Unfortunately, orderedPairs is not provided as a part of lua, you can copy the implementation from here though.
The Lua sort docs provide a good solution
local function pairsByKeys (t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
end
return iter
end
Then you traverse the sorted structure
local t = { b=1, a=2, z=55, c=0, qa=53, x=8, d=7 }
for key,value in pairsByKeys(t) do
print(" " .. tostring(key) .. "=" .. tostring(value))
end
There is no notion of order in Lua tables: they are just sets of key-value pairs.
The two tables below have exactly the same contents because they contain exactly the same pairs:
t = { [223] = "asd" ,[23] = "fgh",[543]="hjk",[7]="qwe"}
t = {[7]="qwe",[23] = "fgh",[223] = "asd" ,[543]="hjk"}
I have the following string:
mystring = "a=test;b=12345"
I would like to know how to initialize a table in one shot, assign it the value of the string. The string originates from another external application, and if possible I want to avoid having to split it up. Something like this:
mytable = {mystring:gsub(";",",")}
Is it possible to do something like this? I know how to do it in multiple steps... but just wondering if it's possible to do it all at once.
Here's what I've tried and the respective output:
> mystring = "a=123;b=2345"
> myarray = {mystring:gsub(";",",")}
> for key,value in pairs(myarray) do print(key,value) end
1 a=123,b=2345
2 1
>
whereas I was hoping to end up with an array / table where like this:
key value
a 123
b 2345
-- Lua 5.2+ required
function string_to_table (str)
local result = {}
load(str, '', 't', setmetatable({}, {
__index = function(t,k) return k end,
__newindex = result
}))()
return result
end
mytable = string_to_table("a=test;b=12345;c=a") -- {a="test", b=12345, c="a"}
Try this, which lets Lua do the hard work:
function parse(s)
local t={}
load(s,"",nil,t)()
return t
end
mytable=parse("a=123;b=2345")
for k,v in pairs(mytable) do print(k,v) end
Note that this executes the code in the given string, which may be dangerous if it comes from an untrusted source. On the other hand, the damage is limited because the code is executed in an empty environment and so cannot affect existing variables. Malicious code may contain infinite loops or consume all memory, though.
mytable = {}
for key, value in string.gmatch("a=123;b=456", "(%w+)=(%w+)") do
mytable[key] = value
end
print(mytable.a, mytable.b)
Returns:
123
456
as expected. This only works, of course, with alphanumeric and no punctuation.
Following is a lua code to read a table with word indexes.
reading this into another table and printing it in output gives random order everytime it is run.
earthquakes = {
date8 = "1992/01/17",
date7 = "1971/02/09",
date6 = "2010/04/04",
date5 = "1987/10/19"
}
sf = string.format
earthquake_num ={}
for k, v in pairs(earthquakes) do
table.insert(earthquake_num, {key=k,value=v})
end
for i, v in pairs (earthquake_num) do
print(sf(" row %d key = %s", i, v.value))
end
OUTPUT :
everytime in different order
This is special feature of Lua 5.2.1 :-)
But what for this feature was introduced?
Anyway, you should not rely on ordering generated by pairs function.
EDIT :
This feature was introduced to fight hash collision attacks on web servers that are using Lua.
Randomized hash algorithm prevents easy generating of strings with equal hashes.
Ordering of table keys generated by pairs function depends on hashes of strings for string-type keys, so string keys are happened to be mixed up on every program run.
From Lua PiL on iterators:
The pairs function, which iterates over all elements in a table, is
similar, except that the iterator function is the next function, which
is a primitive function in Lua:
function pairs (t)
return next, t, nil
end
The call next(t, k), where k is a key of the table t, returns a next key
in the table, in an arbitrary order. (It returns also the
value associated with that key, as a second return value.) The call
next(t, nil) returns a first pair. When there are no more pairs, next
returns nil.
And the enumeration for next states:
next (table [, index])
The order in which the indices are enumerated is not specified,
even for numeric indices. (To traverse a table in numeric order, use a numerical for or the ipairs function.)
As Egor says the pairs iterator returns table values in an arbitrary order. To sort data and return it in a sequenced format you need to use ipairs for example
earthquakes = {
date8 = "1992/01/17",
date7 = "1971/02/09",
date6 = "2010/04/04",
date5 = "1987/10/19"
}
sf = string.format
earthquake_num ={}
for k, v in pairs(earthquakes) do
table.insert(earthquake_num, {key=k,value=v})
end
table.sort(earthquake_num,function(a, b) return a.value < b.value end)
for i, v in ipairs (earthquake_num) do
print(sf(" row %d key = %s", i, v.value))
end
see lua: iterate through all pairs in table for more information.