I'm relatively new to the Lua language and there's something I'm obviously missing about table structures.
I'm trying to create a table of tables, with each table in the table having a key and the value being the respective table.
Ok, that statement can be confusing. Here's an example:
{{ key = "RC", value = {1, 2, 3, 4}},
{ key = "M", value = {4, 8, 7}},
{ key = "D", value = {3, 8, 9}}
...}
for this I used the following algorithm:
local listOfLists = {};
...
if condition1 then
listOfLists[key1] = list1;
end
...
if condition2 then
listOfLists[key2] = list2;
end
...
And so on...
I hope to use the keys to later determine which lists have been added to the table.
But the thing is, no lists seem to be added to the table even if all the conditions are met.
I can use table.insert(listOfLists, list1) in place of listOfLists[key1] = list1 but then I won't be able to tell which lists were added to the collection.
Ant suggestions?
Lua tables are a flexible data structure. Elements are key-value pairs. A key is any Lua value except nil. A value can have any value except nil. Assigning nil to the value obliterates the pair.
The (possibly empty) subset of a table that has key values of the number type that are integers from 1 to n is called a sequence. n is determined as the last such key that is paired with a nil value. Several table functions and operators work only with sequences.
Table constructors allow several syntaxes for keys:
Implied via a sequence: {1, 2, 3}
Explicit keys: {[1] = 1, [3] = 3, ["two"] = "value"}
Identifier keys: {one = 1, two = 2}
A table constructor can use any combination of them.
You have defined a sequence of elements, each of which is a table with two elements, the
second of which is a sequence.
It appears you want keys to be strings and values to be sequences:
{
RC = {1, 2, 3, 4},
M = {4, 8, 7},
D = {3, 8, 9}
}
It's hard to understand, what do you wanna achieve. So, if you want more specific answer, provide more info.
You can create associative table of tables.
local map = {}
map["key"] = { 1, 2, 3, 4 }
print(map.key[3])
Or you can create an array of tables
local vector = {}
vector[1] = { 1, 2, 3, 4 }
print(vector[1][2])
Or you can combine approaches.
To create
{{ key = "RC", value = {1, 2, 3, 4}},
{ key = "M", value = {4, 8, 7}},
{ key = "D", value = {3, 8, 9}}
...}
You can use table constructor or smth from code.
local tbl = { { key = "RC", value = {1, 2, 3, 4}} } -- init first elem from constructor
table.insert(tbl, { key = "M", value = {4, 8, 7}}) -- table insert & constructor
tbl[2] = {} -- Array-based access.
tbl[2].key = "D" --key access
tbl[2]["value"] = { 3, 8, 9 } -- other way
Note, that each table consists of two parts: vector for sequental keys from 1 to N, and map otherwise. Some functions, like table length operator or ipairs iterator are guaranteed to work only with vector-part of table. But they are significantly faster.
EDIT: (last paragraph explanation)
If you have a table with some keys and want to iterate through, you can use ipairs or pairs.
ipairs is ordered, and goes from 1 to first not-nil element. It doesn't iterate over not-integer keys. pairs goes trough any key, but doesn't guarantee order.
local map = { 1, 2, 3, key = 6, [5] = 5 }
for i, v in ipairs(map) do
print(v) -- will output 1, 2, 3. first nil element is map[4]. map[5] will mot be visited.
end
for i, v in pairs(map) do -- NOTE pairs usage
print(v) -- will output 1, 2, 3, 5, 6 in ANY order
end
map[4] = 4 -- Fill gap
for i, v in ipairs(map) do
print(v) -- will output 1, 2, 3, 4, 5. Now first nil element is map[6]
end
Length operator works similar to ipairs, it doesn't count elements not visited by ipairs method.
table.maxn works with numerical indices, and will return zero for your table.
Reference say that table.maxn
Returns the largest positive numerical index of the given table, or zero if the table has no positive numerical indices. (To do its job this function does a linear traversal of the whole table.)
Little example about length and table.maxn
local a = { 1, 2, 3, [5] = 5}
print(table.maxn(a)) -- 5
print(#a) -- 3
a = { key = 4 }
print(table.maxn(a)) -- 0
print(#a) -- 0
print(a["key"]) -- 4, nothing is lost
local num = 0
for _, __ in pairs(a) do num = num + 1 end
print(num) -- 1 We find it.
Related
i have a problem with my Script if i try to loop thought my list the output is completly random shuffled
minimal Code:
list = {
numbers = {
number1 = 1,
number2 = 2,
number3 = 3,
number4 = 4,
number5 = 5,
number6 = 6,
number7 = 7,
}
}
for k, numbers in pairs(list) do
for k, number in pairs(numbers) do
print(number)
end
end
output:
5
7
2
3
4
6
1
the only fix i figured out is to remove the variables number1 to number7
and just enter the numbers
Lua tables do not have an order.
In addition to that you're using pairs which internally uses next.
From the Lua manual:
The order in which the indices are enumerated is not specified, even
for numeric indices. (To traverse a table in numerical order, use a
numerical for.)
In your case the keys have a numeric component so you could simply create them in a numeric loop.
local numbers = {
number1 = 1,
number2 = 2,
number3 = 3,
number4 = 4,
number5 = 5,
number6 = 6,
number7 = 7,
}
for i = 1, 7 do
print(numbers["number"..i])
end
For other non-numeric keys you would have to use a second table that lists the keys in an ordered sequence:
local numbers = { bob = 1, bill = 3, john = 2}
local orderedKeys = { "bob", "john", "bill"}
for k,v in ipairs(orderedKeys) do
print(numbers[v])
end
A numeric loop will always work for any integer keys.
local numbers = {
[0] = 0,
[5] = 5,
[3] = 3,
[1] = 0,
}
for i = 0, 5 do
if numbers[i] then
print(numbers[i])
end
end
Read through this carefully:
A table with exactly one border is called a sequence. For instance,
the table {10, 20, 30, 40, 50} is a sequence, as it has only one
border (5). The table {10, 20, 30, nil, 50} has two borders (3 and 5),
and therefore it is not a sequence. (The nil at index 4 is called a
hole.) The table {nil, 20, 30, nil, nil, 60, nil} has three borders
(0, 3, and 6) and three holes (at indices 1, 4, and 5), so it is not a
sequence, too. The table {} is a sequence with border 0. Note that
non-natural keys do not interfere with whether a table is a sequence.
Things like ipairs, the length operator #, table.sort, table.concat and others only work with sequences.
Keys that do not contribute to the sequence are ignored by those functions. You can only loop over all keys of a table with next or pairs respectively. But then order is not guaranteed.
I am trying to loop through every other element in an table but I cannot find a way to do so.
Any help is appreciated.
Thank you.
It depends what kind of table you're working with. If you have an array-like table, you can use a simple for-loop :
local t = {1, 2, 3, 4, 5, 6, 7, 8}
-- start at 1, loop until i > the length of t, increment i by 2 every loop
for i = 1, #t, 2 do
local val = t[i]
print(val) -- will print out : 1, 3, 5, 7
end
But if you have a dictionary-like table, you will need something to track which key to skip. You could use a simple boolean to keep track, but be aware that there is no guaranteed order of a dictionary-like table.
local t = {
a = 1,
b = 2,
c = 3,
d = 4,
}
local shouldPrint = true
for k, v in pairs(t) do
-- only print the value when it's true
if shouldPrint then
print(k, v) -- will probably print a, 1 and c, 3
end
-- swap shouldPrint's value every loop
shouldPrint = !shouldPrint
end
Maybe try this
local count = 0
for i = 1 , #table/2 do
table[count + i].value = value
count = count + 1
end
Add to the count as you go down
x = {1, 2, 3}
y = {4, 5, 6}
z = x + y
I have two tables x and y and just want to create a third one which is just the sum of elements in them. I use the above LUA code in an effort but this gives error input:3: attempt to perform arithmetic on a table value (global 'x')...
Like, I want the result z = {5, 7, 9}
Please suggest functions that will be helpful, or please help me form such a function in LUA.
Thanks
Yes, iterate and check with table.concat()
do...
x = {1, 2, 3}
y = {4, 5, 6}
z = {}
-- First check same table length and if so then add sums to z table
if #x==#y then
for i=1,#x do
z[i]=x[i]+y[i]
end
end
print(table.concat(z,' '))
-- puts out: 5 7 9
...end
You cannot add tables in Lua unless you implement the __add metamethod.
For an element wise sum of two sequences simply do this:
function sumElements(t1,t2)
local result = {}
for i = 1, math.min(#t1, #t2) do
result[i] = t1[i] + t2[i]
end
return result
end
of course you should verify your inputs and think about how you want to deal with mismatching table sizes. Let's say t1 has 3 elements and t2 has 5, will you just have 3 result values or will you add 0 to the remaining 2?
I have the following array of numbers.
arr = {3412323450, 8912745671, 3212367894}
I want to convert it into a simple two-dimensional matrix.
mat = {
{3, 4, 1, 2, 3, 2, 3, 4, 5, 0},
{8, 9, 1, 2, 7, 4, 5, 6, 7, 1},
{3, 2, 1, 2, 3, 6, 7, 8, 9, 4}
}
Initially, I would iterate over arr, convert it into a string, then split the string, iterate over each string char and convert it back to number storing every row and number in mat accordingly. This would be really ugly.
Is there a more conventional method to convert an array into a matrix in
Lua?
Is there a luarock package that people use frequently to convert an array to a matrix?
Personally I think converting to a string and grabbing all of the digits is far prettier than the alternatives (massively dividing by 10, or any other elaborate means you can think of). This is especially true if you wrap the operations up in functions, so your conversions are not constantly appearing throughout your code.
function Digits(n)
local digits = {}
for d in tostring(n):gmatch('%d') do
digits[#digits+1] = tonumber(d)
end
return digits
end
function ArrayToMatrix(array)
local matrix = {}
for i,v in ipairs(array) do
matrix[i] = Digits(v)
end
return matrix
end
Ok, here is my try.
arr = {3412323450, 8912745671, 3212367894}
function arr2matrix(arr)
local mat = {}
for i, row in ipairs(arr) do
mat[i] = {}
local j = 0
row_str = string.gsub(row, '%d', '%0 ')
for c in string.gmatch(row_str, '%S') do
j = j + 1
mat[i][j] = tonumber(c)
end
end
return mat
end
-- checking the result
m = arr2matrix(arr)
for i=1, #m do
for j=1, #m[i] do
io.write(m[i][j]..',')
end
io.write('\n')
end
Running the above gives:
3,4,1,2,3,2,3,4,5,0,
8,9,1,2,7,4,5,6,7,1,
3,2,1,2,3,6,7,8,9,4,
How do I get the highest integer in a table in Lua?
math.max(unpack({1, 2, 3, 4, 5}))
A generic function for achieving this:
function max(t, fn)
if #t == 0 then return nil, nil end
local key, value = 1, t[1]
for i = 2, #t do
if fn(value, t[i]) then
key, value = i, t[i]
end
end
return key, value
end
Which is used like this:
print(max({1,2,3,4,1,2,37,1,0}, function(a,b) return a < b end)) --> 7 37
loltable = {1, 2, 3, 4, 1, 2, 37, 1, 0}
table.sort(loltable)
print(loltable[#loltable])
The other answer by ponzao is good, but to answer your question more specifically, if you just want to get the highest number (and not the index as well), I usually do this:
function max(a)
local values = {}
for k,v in pairs(a) do
values[#values+1] = v
end
table.sort(values) -- automatically sorts lowest to highest
return values[#values]
end
print(max({1, 2, 3, 4, 1, 2, 37, 1, 0})) --> 37
To take it a step further and include only the array part of the table and filter out for only number values (to prevent errors), you can add some type checks:
function max(a)
local values = {}
for k,v in pairs(a) do
if type(k) == "number" and type(v) == "number" then
values[#values+1] = v
end
end
table.sort(values) -- automatically sorts lowest to highest
return values[#values]
end
print(max({1, 2, 3, 4, 1, 2, 37, 1, 0})) --> 37
The logic is as follows:
Create an empty table (array)
Iterate over all keys via pairs (ipairs() stops at first nil, and so does using a for loop with #)
Add each value to the array (after verifying type in second code block)
Sort the array from highest to lowest
Return the value of the last element (after sort, it will be at the end).
I know this is an old question so the OP probably doesn't need this anymore, but this page currently ranks high on Google so hopefully this can help someone else who stumbles upon this page.
If your table is an array (only numeric indices >0) then use table.sort and take t[#t] (however, this changes the table).
Other approach would be like this
m={0,0}
for k,v in pairs(t) do
if m[1]<v then
m[1]=v
m[2]=k
end
end
print("Maximum of "..m[1].." at index "..m[2])
Lua comes with a function to get the highest integer key if thats what you wanted...
table.maxn
you are forgetting to add table before unpack like this
local save = math.max(table.unpack({1, 2, 3, 4, 5}))
print(save)
this should work if you want to find the max or min number