Lua: set of k-dimensional points - lua

I want to make sure that kD points which I generate randomly don't happen to be identical. To test this efficiently, I want to use a set (at least that's what I would do in C++).
I know that in Lua tables can be used as sets by inserting the object as value with any non-nil key (typically just true or an integer for multisets).
But the problem is that tables in Lua are by default just compared w.r.t. their address, which is of course different even if all the vector components (in my case) are equal.
So I thought I'd implement a equal and/or less than metamethod for my points. But this didn't work (see code below). Can anybody help?
local k = 3
local mt = {}
mt.__eq = function( a, b )
for dim = 1, k do
if a[dim] ~= b[dim] then return false end
end
return true
end
mt.__lt = function( a, b )
for dim = 1, k do
if a[dim] < b[dim] then
return true
elseif a[dim] > b[dim] then
return false
end
end
return false -- equal
end
local set = {}
local p1 = { 1, 2, 3 }
setmetatable( p1, mt )
set[p1] = true
local p2 = { 1, 2, 3 }
setmetatable( p2, mt )
set[p2] = true -- should just overwrite the old value
print( "p1 == p2 --> "..tostring( p1 == p2 ) )
print( "p1 < p2 --> "..tostring( p1 < p2 ) )
local setSize = 0
for _, _ in pairs( set ) do
setSize = setSize + 1
end
print( "Size of the set: "..setSize )

Lua has no facilities for allowing what you're trying to do. That is, there's no metamethod trickery that can make two different pieces of userdata or two different tables map to the same index to the table indexing system.
You'll have to do this manually. You can effectively write your own set, by keeping a list of vectors sorted. table.sort can do the job, since you already have an appropriate __lt metamethod.

If anyone is interested: I have come up with another work-around that has worked for me.
One can use a set of x-coordinates and instead of associating the set items with just "true" or "1", the respective values are sets themselves (of y-coordinates); and so on.
This leads to a tree-like structure where the path to each leaf represents a point (sequence of coordinates) and points with the same first coordinates have common parent nodes. Also all points are unique.

Related

What does [{n,{}}] do in lua?

As you can tell I'm a beginner in lua. I am trying to understand a function I'm stuck at what the following code segment does?
It is used in the following code snippet in the last line:
function classify(txt_dir, img_dir, cls_list)
local acc = 0.0
local total = 0.0
local fea_img = {}
local fea_txt = {}
for fname in io.lines(cls_list) do
local imgpath = img_dir .. '/' .. fname .. '.t7'
local txtpath = txt_dir .. '/' .. fname .. '.t7'
fea_img[#fea_img + 1] = extract_img(imgpath)
fea_txt[#fea_txt + 1] = extract_txt(txtpath)
end
for i = 1,#fea_img do
-- loop over individual images.
for k = 1,fea_img[i]:size(1) do
local best_match = 1
local best_score = -math.huge
for j = 1,#fea_txt do
local cur_score = torch.dot(fea_img[i][{k,{}}], fea_txt[j])
From my understanding, fea_img is a lua table. Is the line fea_img[i][{k,{}}] some sort of slicing for the value for the key 'i' in the table fea_img?
I tried searching for more examples and found this being used here too (last line):
for i = 1,nsamples,batchsize do
-- indices
local lasti = math.min(i+batchsize-1,nsamples)
local m = lasti - i + 1
-- k-means step, on minibatch
local batch = x[{ {i,lasti},{} }]
Any help on this would be really appreciated. Thank you!
In lua you can access a specific index on a table in multiple ways. Like these two examples
local myValue = someTable.theIndex
-- or
local myOtherValue = someTable[2]
So the construct you see here is to access some values from a (nested) table.
Also in lua you can use anything except nil as a index, so even tables are possible.
The line
fea_img[i][{k,{}}]
Can be extended to this:
local index1 = i -- i in this case is your loop variable
local index2 = { k , { } } -- This creates a table with 2 values, the first one will be the vaule of the var k, the second one is an empty table
local value1 = fea_img[index1] -- This will get you a table
local value2 = value1[index2] -- This will get the same as: fea_img[i][{k,{}}]
Correction and Addition:
As Nicol Bolas already said in the comments: The index must be an exact match. Which means it literally has to be the same table, which is not the case for the presented code from you. Either you dropped code you thought is unnecessary or fea_img has some some kind of metatable on it.
In the case of
local k = 2
local table1 = {k, { } }
local table2 = {k, { } }
table2 and table1 do have the exact same content. But they are not the same table. Which will lead to nil always being retrieved if one is used to store data in a table and the other is used to get it back.
Syntactically, t[k] is indexing a table with a key. Normally, if there is a record in the table with the key k, its value is returned. Nothing more, nothing less.
If fea_img[i] was a normal table, {k,{}} would always return nil, since table indices are resolved based on their identity ({k,{}} is always a new table). Based on your code, I have to conclude that the elements of fea_img (i.e. what extract_img returns) are not normal tables.
In Lua, you can override the indexing operation using a metatable. If you index a value that has a metatable with __index, it will be used if there is no matching record in the table:
local t = {}
setmetatable(t, {
__index = function(t, k)
return k
end
})
print(t[{}])
This table has a metatable associated with it, which is used in the indexing operation. In this case __index returns the key, but whatever library you are using might provide more complex behaviour.
This is specific to the library you are using, not something related to the Lua syntax.

Check for identical elements in a table in Lua?

How would you check a table for three identical elements (looking for three L's)?
table = {nil, nil, L, nil, L} -> false
table = {L, L, nil, nil, L} -> true
Really would appreciate some help!
EDIT: Ok I've got this, but it only outputs false even when there are three or more L's (and does so five times for every check?). Sorry if it seemed like I was trying to get the code for it, I'm genuinely trying to learn! :)
for k, v in pairs( threeL_table ) do
local count = 0
if k == 'L' then
count = count + 1
end
if count == 3 then
print('true')
else
print('false')
end
end
You were almost there. You need to test the values v against 'L', not the keys k. Also, I suppose you want to print the message only once after the scan is concluded; if so, put the if-statement outside of the for-loop. (In this case, you should define count outside of the for-loop, too, otherwise you would not see it once it has ended).
local count = 0
for k, v in pairs( threeL_table ) do
if v == 'L' then -- you need to check for the values not the keys
count = count + 1
end
end
if count == 3 then -- move this out of the for-loop
print('true')
else
print('false')
end
I will not give you any code as you did not show any own efforts to solve the problem.
How would you check a table for three identical elements? Well you count them.
Loop over the table and for every distinct value you create a new counter. You could use another table for that. Once one of those counters reaches 3 you know that you have three identical values.
Another way to solve this.
function detectDup(t,nDup)
table.sort(t)
local tabCount = {}
for _,e in ipairs(t) do
tabCount[e] = (tabCount[e] or 0) + 1
if tabCount[e] >= 3 then
print("The element '" .. e .. "' has more than 3 repetitions!")
return true
end
end
return false
end
print(detectDup({'L', 'L','A','B'},3))
print(detectDup({'L', 'L','A','B','L',},3))

A better way to assign multiple return values to table keys in Lua

Assume I have a function that returns multiple values. I happen to be working with LÖVE's (Image):getDimensions. This returns two values, which I know to be width,height. I want to assign them to a new table, as an array. I would like named (string) keys. So for instance, I would like to assign the return values of the getDimensions() function to a new table with keys width and height, respectively.
I know the following works...
image = {}
image.data = love.graphics.newImage('myimage.png')
image.size = {}
image.size.width, image.size.height = image.data:getDimensions()
I'm wondering if there is any sort of syntactic sugar I can use, or any use of standard library functions that will allow a syntax more along the lines of...
image.size = { width, height = image.data:getDimensions() }
I know the above line does not work, along with many variations I've tried, including various attempts to use unpack(). I'm new to Lua (~2 days in now), so maybe there is another standard function or best practice that I'm unaware of that will associate a table of keys to an array-like table. Thanks!
You can write your own functions:
local function set_fields(tab, fields, ...)
-- fields is an array of field names
-- (use empty string to skip value at corresponging position)
local values = {...}
for k, field in ipairs(fields) do
if field ~= "" then
tab[field] = values[k]
end
end
return tab
end
local function get_fields(tab, fields)
local values = {}
for k, field in ipairs(fields) do
values[k] = tab[field]
end
return (table.unpack or unpack)(values, 1, #fields)
end
Usage example #1:
image.size = set_fields({}, {"width", "height"}, image.data:getDimensions())
Usage example #2:
Swap the values on-the-fly!
local function get_weekdays()
return "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
end
-- we want to save returned values in different order
local weekdays = set_fields({}, {7,1,2,3,4,5,6}, get_weekdays())
-- now weekdays contains {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}
Usage example #3:
local function get_coords_x_y_z()
return 111, 222, 333 -- x, y, z of the point
end
-- we want to get the projection of the point on the ground plane
local projection = {y = 0}
-- projection.y will be preserved, projection.x and projection.z will be modified
set_fields(projection, {"x", "", "z"}, get_coords_x_y_z())
-- now projection contains {x = 111, y = 0, z = 333}
Usage example #4:
If require("some_module") returns a module with plenty of functions inside, but you need only a few of them:
local bnot, band, bor = get_fields(require("bit"), {"bnot", "band", "bor"})
Using a class construct, I have come up with the following...
Size = {}
Size.mt = {}
Size.prototype = { width = 0, height = 0 }
function Size.new (dimensions)
local size = setmetatable({}, Size.mt)
if dimensions ~= nil and type(dimensions) == 'table' then
for k,v in pairs(dimensions) do
size[k] = v
end
end
return size
end
Size.mt.__index = function (t, k)
if k == 'width' or k == 'height' then
rawset(t, k, Size.prototype[k])
return t[k]
else
return nil
end
end
Size.mt.__newindex = function (t, k, v)
if k == 1 or k == 'width' then
rawset(t, 'width', v)
elseif k == 2 or k == 'height' then
rawset(t, 'height', v)
end
end
Then I can initialize a Size object in a number of ways
Using multiple return values:
image.size = Size.new{image.data:getDimensions()}
image.size = Size.new(table.pack(image.data:getDimensions())
Using default values:
image.size = Size.new()
image.size = Size.new{}
image.size = Size.new({})
Using mixed array and hash tables:
image.size = Size.new({height=20, width=30})
image.size = Size.new({height=20, 30})
There are pros and cons to this approach vs. Egor's (utility function), which is what I was considering doing if there wasn't a simple syntax trick or an existing function that I was unaware of.
Pros:
(personal) learning experience with OO constructs in Lua
I can limit the number of actual keys on the table, while allowing 'synonyms' for those keys to be added by expanding the accepted values in the if/else logic of __index and __newindex
Explicit definition of fields in the table, without needing to worry about syncing a table of keys with a table of values (as with a general purpose utility function)
Cons
would need to repeat this pattern for each data structure where I wanted this behavior
costly, a lot of overhead for what amounts to a very small difference to the consumer
I'm sure I can make this approach more robust in time, but I would appreciate any feedback.

Lua: Creating tables

I'm attempting to use a table as a means to do two things at once. For example:
s = passengers -- user input
t = {[3] = car, [7] = bus, [24] = plane, [45] = train}
for k,v in ipairs t do
if s = k then
z = v * 10 -- cost per person
end
end
Now this is extremely basic for what I'm trying to do. I have a list of about 12 items that each have their own number. I want to know if I can do what I did above with the table and provide each of the 12 items with their own key value and then use that ? This key value would represent each items particular, unique number. Also, can I then use that key's value in a later equation, such as above?
If your keys are unique, your data structure. The point of a table key is direct access to the corresponding value.
This has the same effect as your loop:
local v = t[s] -- value for s or nil if s is not a key
if v != nil then
z = v * 10
end
(Or, more exactly the same: local v = rawget(t,s) to account for cases where t has an __index metamethod.)
If we can assume that v will never be false (which would cause an error at false * 10) then it can be written more naturally (which skips that error):
local v = t[s]
if v then
z = v * 10
end

Concatenation of tables in Lua

ORIGINAL POST
Given that there is no built in function in Lua, I am in search of a function that allows me to append tables together. I have googled quite a bit and have tried every solutions I stumbled across but none seem to work properly.
The scenario goes like this: I am using Lua embeded in an application. An internal command of the application returns a list of values in the form of a table.
What I am trying to do is call that command recursively in a loop and append the returned values, again in the form of a table, to the table from previous iterations.
EDIT
For those who come across this post in the future, please note what #gimf posted. Since Tables in Lua are as much like arrays than anything else (even in a list context), there is no real correct way to append one table to another. The closest concept is merging of tables. Please see the post, "Lua - merge tables?" for help in that regard.
Overcomplicated answers much?
Here is my implementation:
function TableConcat(t1,t2)
for i=1,#t2 do
t1[#t1+1] = t2[i]
end
return t1
end
If you want to concatenate an existing table to a new one, this is the most concise way to do it:
local t = {3, 4, 5}
local concatenation = {1, 2, table.unpack(t)}
Although I'm not sure how good this is performance-wise.
And one more way:
for _,v in ipairs(t2) do
table.insert(t1, v)
end
It seems to me the most readable one - it iterates over the 2nd table and appends its values to the 1st one, end of story. Curious how it fares in speed to the explicit indexing [] above
A simple way to do what you want:
local t1 = {1, 2, 3, 4, 5}
local t2 = {6, 7, 8, 9, 10}
local t3 = {unpack(t1)}
for I = 1,#t2 do
t3[#t1+I] = t2[I]
end
To add two tables together do this
ii=0
for i=#firsttable, #secondtable+#firsttable do
ii=ii+1
firsttable[i]=secondtable[ii]
end
use the first table as the variable you wanted to add as code adds the second one on to the end of the first table in order.
i is the start number of the table or list.
#secondtable+#firsttable is what to end at.
It starts at the end of the first table you want to add to, and ends at the end of the second table in a for loop so it works with any size table or list.
In general the notion of concatenating arbitrary tables does not make sense in Lua because a single key can only have one value.
There are special cases in which concatenation does make sense. One such is for tables containing simple arrays, which might be the natural result of a function intended to return a list of results.
In that case, you can write:
-- return a new array containing the concatenation of all of its
-- parameters. Scaler parameters are included in place, and array
-- parameters have their values shallow-copied to the final array.
-- Note that userdata and function values are treated as scalar.
function array_concat(...)
local t = {}
for n = 1,select("#",...) do
local arg = select(n,...)
if type(arg)=="table" then
for _,v in ipairs(arg) do
t[#t+1] = v
end
else
t[#t+1] = arg
end
end
return t
end
This is a shallow copy, and makes no attempt to find out if a userdata or function value is a container or object of some kind that might need different treatment.
An alternative implementation might modify the first argument rather than creating a new table. This would save the cost of copying, and make array_concat different from the .. operator on strings.
Edit: As observed in a comment by Joseph Kingry, I failed to properly extract the actual value of each argument from .... I also failed to return the merged table from the function at all. That's what I get for coding in the answer box and not testing the code at all.
If you want to merge two tables, but need a deep copy of the result table, for whatever reason, use the merge from another SO question on merging tables plus some deep copy code from lua-users.
(edit
Well, maybe you can edit your question to provide a minimal example... If you mean that a table
{ a = 1, b = 2 }
concatenated with another table
{ a = 5, b = 10 }
should result in
{ a = 1, b = 2, a = 5, b = 10 }
then you're out of luck. Keys are unique.
It seems you want to have a list of pairs, like { { a, 1 }, { b, 2 }, { a, 5 }, { b, 10 } }. You could also use a final structure like { a = { 1, 5 }, b = { 2, 10 } }, depending on your application.
But the simple of notion of "concatenating" tables does not make sense with Lua tables.
)
Here is an implementation I've done similar to RBerteig's above, but using the hidden parameter arg which is available when a function receives a variable number of arguments. Personally, I think this is more readable vs the select syntax.
function array_concat(...)
local t = {}
for i = 1, arg.n do
local array = arg[i]
if (type(array) == "table") then
for j = 1, #array do
t[#t+1] = array[j]
end
else
t[#t+1] = array
end
end
return t
end
Here is my implementation to concatenate a set of pure-integer-indexing tables, FYI.
define a function to concatenate two tables, concat_2tables
another recursive function concatenateTables: split the table list by unpack, and call concat_2tables to concatenate table1 and restTableList
t1 = {1, 2, 3}
t2 = {4, 5}
t3 = {6}
concat_2tables = function(table1, table2)
len = table.getn(table1)
for key, val in pairs(table2)do
table1[key+len] = val
end
return table1
end
concatenateTables = function( tableList )
if tableList==nil then
return nil
elseif table.getn(tableList) == 1 then
return tableList[1]
else
table1 = tableList[1]
restTableList = {unpack(tableList, 2)}
return concat_2tables(table1, concatenateTables(restTableList))
end
end
tt = {t1, t2, t3}
t = concatenateTables(tt)
-- Lua 5.1+
function TableAppend(t1, t2)
-- A numeric for loop is faster than pairs, but it only gets the sequential part of t2
for i = 1, #t2 do
t1[#t1 + 1] = t2[i] -- this is slightly faster than table.insert
end
-- This loop gets the non-sequential part (e.g. ['a'] = 1), if it exists
local k, v = next(t2, #t2 ~= 0 and #t2 or nil)
while k do
t1[k] = v -- if index k already exists in t1 then it will be overwritten
k, v = next(t2, k)
end
end
EDIT
Here's a better solution, the other one tended to overwrite numeric keys, the usage is still the same:
function merge(...)
local temp = {}
local index = 1
local result = {}
math.randomseed(os.time())
for i, tbl in ipairs({ ... }) do
for k, v in pairs(tbl) do
if type(k) == 'number' then
-- randomize numeric keys
k = math.random() * i * k
end
temp[k] = v
end
end
for k, v in pairs(temp) do
if type(k) == "number" then
-- Sort numeric keys into order
if result[index] then
index = index + 1
end
k = index
end
result[k] = v
end
return result
end
ORIGINAL
A wee bit late to the game, but this seems to work for me:
function concat(...)
local result = {}
for i, tbl in ipairs({...}) do
for k, v in pairs(tbl) do
if type(k) ~= "number" then
result[k] = v
else
result[i] = v
end
end
end
return result
end
It might be a bit overcomplicated, but it takes an infinite amount of arguments, and works for both key-value pairs and regular "arrays" (numbers as keys). Here's an example
I like the simplicity in #Weeve Ferrelaine answer, but mutations may cause many issues and in general, are not desirable.
Version with NO MUTATION.
---#param t1 {}
---#param t2 {}
function TableConcat(t1,t2)
local tOut = {}
for i = 1, #t1 do
tOut[i] = t1[i]
end
for i = #t1, #t1 + #t2 do
tOut[i] = t2[i]
end
return tOut
end
Original implementation, that's mutating t1.
function TableConcat(t1,t2)
for i=1,#t2 do
t1[#t1+1] = t2[i]
end
return t1
end
Use table.concat:
http://lua-users.org/wiki/TableLibraryTutorial
> = table.concat({ 1, 2, "three", 4, "five" })
12three4five
> = table.concat({ 1, 2, "three", 4, "five" }, ", ")
1, 2, three, 4, five
> = table.concat({ 1, 2, "three", 4, "five" }, ", ", 2)
2, three, 4, five
> = table.concat({ 1, 2, "three", 4, "five" }, ", ", 2, 4)
2, three, 4

Resources