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
Related
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?
Like in python I can use slice. Like following
b=[1,2,3,4,5]
a=b[0:3]
Can I do that kind of operation in Lua without a loop. Or Loop is the most efficient way to do that
By creating a new table using the result of table.unpack (unpack before Lua 5.2):
for key, value in pairs({table.unpack({1, 2, 3, 4, 5}, 2, 4)}) do
print(key, value)
end
This generates...
1 2
2 3
3 4
(Tested in Lua 5.3.4 and Lua 5.1.5.)
There's no syntax sugar for doing this, so your best bet would be doing it via a function:
function table.slice(tbl, first, last, step)
local sliced = {}
for i = first or 1, last or #tbl, step or 1 do
sliced[#sliced+1] = tbl[i]
end
return sliced
end
local a = {1, 2, 3, 4}
local b = table.slice(a, 2, 3)
print(a[1], a[2], a[3], a[4])
print(b[1], b[2], b[3], b[4])
Keep in mind that I haven't tested this function, but it's more or less what it should look like without checking input.
Edit: I ran it at ideone.
xlua package has table.splice function. (luarocks install xlua)
yourTable = {1,2,3,4}
startIndex = 1; length = 3
removed_items, remainder_items = table.splice(yourTable, startIndex, length)
print(removed_items) -- 4
print(remainder_items) -- 1,2,3
see: https://github.com/torch/xlua/blob/master/init.lua#L640
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.
myTable = {}
myTable["foo"] = 12
myTable["bar"] = "blah"
print(#myTable) -- this prints 0
Do I actually have to iterate through the items in the table to get the number of keys?
numItems = 0
for k,v in pairs(myTable) do
numItems = numItems + 1
end
print(numItems) -- this prints 2
I experimented with both the # operator and table.getn(). I thought table.getn() would do what you wanted but as it turns out it's returning the same value as #, namely 0. It appears that dictionaries insert nil placeholders as necessary.
Looping over the keys and counting them seems like the only way to get the dictionary size.
The length operator:
The length of a table t is defined to be any integer index n such that t[n] is not nil and t[n+1] is nil; moreover, if t[1] is nil, n can be zero. For a regular array, with non-nil values from 1 to a given n, its length is exactly that n, the index of its last value. If the array has "holes" (that is, nil values between other non-nil values), then #t can be any of the indices that directly precedes a nil value (that is, it may consider any such nil value as the end of the array).
so only way to get length is iterate over it.
Aside from iterating through the keys manually, it is simple to automatically keep track of it via metamethods. Considering you probably don't want to keep track of every table you make, you can just write a function that will allow you to convert any table into a key-countable object. The following isn't perfect, but I think it would illustrate the point:
function CountedTable(x)
assert(type(x) == 'table', 'bad parameter #1: must be table')
local mt = {}
-- `keys` will represent the number of non integral indexes
-- `indxs` will represent the number of integral indexes
-- `all` will represent the number of both
local keys, indxs, all = 0, 0, 0
-- Do an initial count of current assets in table.
for k, v in pairs(x) do
if (type(k) == 'number') and (k == math.floor(k)) then indxs = indxs + 1
else keys = keys + 1 end
all = all + 1
end
-- By using `__nexindex`, any time a new key is added, it will automatically be
-- tracked.
mt.__newindex = function(t, k, v)
if (type(k) == 'number') and (k == math.floor(k)) then indxs = indxs + 1
else keys = keys + 1 end
all = all + 1
t[k] = v
end
-- This allows us to have fields to access these datacounts, but won't count as
-- actual keys or indexes.
mt.__index = function(t, k)
if k == 'keyCount' then return keys
elseif k == 'indexCount' then return indxs
elseif k == 'totalCount' then return all end
end
return setmetatable(x, mt)
end
Examples of using this would include:
-- Note `36.35433` would NOT be counted as an integral index.
local foo = CountedTable { 1, 2, 3, 4, [36.35433] = 36.35433, [54] = 54 }
local bar = CountedTable { x = 23, y = 43, z = 334, [true] = true }
local foobar = CountedTable { 1, 2, 3, x = 'x', [true] = true, [64] = 64 }
print(foo.indexCount) --> 5
print(bar.keyCount) --> 4
print(foobar.totalCount) --> 6
Live Working Example
Hope this helped! :)
Lua stores table as two separates parts : a hash part and an array part, the len operator only deal with the array part, meaning value indexed by a number value, plus using rules mentioned below, so you don't have any choice for counting "hash" value you need to iterate over the table with pairs() function.