multi key tuple to map a multi value tuple in Lua - lua

Is there a lib in Lua that supports a map from a tuple to a tuple? I have a key {a,b,c} to map to a value {c,d,e}
There are libs such as, http://lua-users.org/wiki/MultipleKeyIndexing for multikey but not where the value is a tuple.

Here's one way to use Egor's suggestion for making a key through string concatenation. Make your own simple insert and get methods for a table, t.
local a, b, c = 10, 20, 30
local d, e, f = 100, 200, 300
local t = {}
t.key = function (k)
local key = ""
for _,v in ipairs(k) do
key = key .. tostring(v) .. ";"
end
return key
end
t.set = function (k, v)
local key = t.key(k)
t[key] = v
end
t.get = function (k)
local key = t.key(k)
return t[key]
end
t.set ({a, b, c}, {d, e, f}) -- using variables
t.set ({40, 50, 60}, {400, 500, 600}) -- using constants
local w = t.get ({a, b, c}) -- using variables
local x = t.get ({40, 50, 60}) -- using constants
print(w[1], w[2], w[3]) -- 100 200 300
print(x[1], x[2], x[3]) -- 400 500 600

Related

Is it possible that key has multi values on Lua script

I want to handle lua table.
Script:
local my_talbe = {}
for key, value in pairs(my_table)
print(key, value)
end
The script returns:
a 80
b 80
c 70
d 40
e 70
f 80
I want to my_table handle like this:
local new_talbe = {}
for key, value in pairs(new_table)
print(key, value)
end
Expected output:
80 {a,b,f} # table
70 {c,e}
40 {d}
Please help me.
If you can change how my_table is created, use #pynexj method.
If you need to convert, something like this should do the job.
local my_table = {
a = 80,
b = 80,
c = 70,
d = 40,
e = 70,
f = 80,
}
-- Invert key and value, but put the keys into buckets/arrays
local function to_multi_key_map(t)
local n = { }
for i,v in pairs(t) do
if n[v] then
table.insert(n[v], i)
else
n[v] = { i }
end
end
return n
end
for i,v in pairs(to_multi_key_map(my_table)) do
print(i, "{" .. table.concat(v, ", ") .. "}")
end
70 {c, e}
80 {b, f, a}
40 {d}

(Lua) How do I break a string into entries on a table?

So I want to take an input like R U R' U' and turn it into a table that contains
R
U
R'
U'
I haven't found an example of code that worked. I have tried this solution from codegrepper, and it didn't work. I have not come up with anything else in my head but my general program, which is supposed to take an input like R and find its place in a table. If R is 1, then it will take the value 1 from another table, which will have the r^ as value 1. Then it will do this with the rest and print it when it is done. So if there is an optimization with this that could make it all quicker than I would like to see it. Thanks and goodbye.
function split(str, pat)
local t = {}
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = str:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then table.insert(t, cap) end
last_end = e + 1
s, e, cap = str:find(fpat, last_end)
end
if last_end <= #str then
cap = str:sub(last_end)
table.insert(t, cap)
end
return t
end
then split it with split(var," ")
local myString = "R U R' U'"
local myTable = {}
for e in string.gmatch(myString, "%S+") do
table.insert(myTable, e)
end
Lua Users Wiki
s:gmatch(pattern)
This returns a pattern finding iterator. The iterator will search
through the string passed looking for instances of the pattern you
passed.
First you need to match all the space-separated parts. You can do this using gmatch. Then you can insert these parts as keys in a hash table, the value being the one-indexed index of the occurrence:
local str = "R U R' U'"
local index = 1
local last_occurrence = {}
for match in str:gmatch"%S+" do
last_occurrence[match] = index
index = index + 1
end
Now you can use your "other table" to obtain the value in constant time:
local other_table = {"r^"}
local value = other_table[last_occurrence.R] -- "r^"

Unpack lua table as object and map them as function arguments

I'm looking for a way to unpack lua table(object, not an array) and map return value as arguments to a function.
Example:
local function f(a, b, c, d)
print(a, b, c, d)
end
--order is messed up on purpose
local object_to_unpack = {
a = 1,
c = 42,
d = 18,
b = 102
}
So Im looking for a way to do something like
f(unpack_and_map(object_to_unpack)) and for function to output 1, 102, 42, 18.
I know about unpack function, but it only works on arrays, not objects, and I don't have any ordering guarantees(as demonstrated in object_to_unpack)
Not sure why you want to unpack that table and not just use it as the functions parameter.
local someTable = {
a = 1,
c = 42,
d = 18,
b = 102,
}
local function f(t)
print(t.a, t.b, t.c, t.d)
end
f(someTable)
If you insist on calling f with a list of expressions you need to create one.
function f(...)
print(...)
end
local args = {}
for _, v in pairs(someTable) do
table.insert(args, v)
end
f(table.unpack(args))
This does not guarantee any order. If you want the list ordered by the keys you need to sort that list prior to calling f.
local keys = {}
for k in pairs(someTable) do
table.insert(keys, k)
end
table.sort(keys)
local args = {}
for _, key in ipairs(keys) do
table.insert(args, someTable[key])
end
f(table.unpack(args))

Lua converting my identifier to a string when I put it into a table?

a = {}
b = "s"
a.b = "white"
a["s"] = 2
local keyset={}
local n=0
for k,v in pairs(a) do
n=n+1
keyset[n]=k
print(type(k))
-- output is String(x2)
end
Does Lua recognize b as a string and not as an identifier if I do a.b?
From the Lua Documentation:
A common mistake for beginners is to confuse a.x with a[x]. The first form represents a["x"], that is, a table indexed by the string "x". The second form is a table indexed by the value of the variable x.
If anyone would like to add on to why Lua does this, feel free to do it! The question is however answered at this point.
UPD Before the for loop, a = {['b'] = 'white', ['s'] = 2}.
Forget about the keyset table; that's not converting anything.
#! /usr/bin/env lua
a = {}
b = "s" -- completely different variable, not used in a
a.b = "white" -- syntactic sugar for a["b"] = "white"
a["s"] = 2 -- variable b just happens to have same value as this key, so it fits
-- at this point there are two entries in a
-- a["b"] = "white" and a["s"] = 2
for k, v in pairs( a ) do
print( 'key:', k, type(k), ' val:', v, type(v) )
end
print( b, a[b] ) -- retrieve value from a["s"] coincidental key fit
key: s string val: 2 number
key: b string val: white string
s 2

Adding _concat to numbers to create number ranges - am I mad?

Just as a random experiment I'm considering adding a __concat() metamethod to the number metatable (usually a new metatable as numbers don't seem to have metatables by default?).
The idea is that I could do something like 3..5 and get back 3, 4, 5.
I could then have a function foo(tbl, ...) that does something with multiple indexes on a table and call it like foo(tbl, 3..5).
Am I barking mad or does this seem like a viable thing to do?
Rough draft of code (not tested yet):
-- get existing metatable if there is one
local m = getmetatable( 0 ) or {};
-- define our concat method
m.__concat = function( left, right )
-- note: lua may pre-coerce numbers to strings?
-- http://lua-users.org/lists/lua-l/2006-12/msg00482.html
local l, r = tonumber(left), tonumber(right);
if not l or not r then -- string concat
return tostring(left)..tostring(right);
else -- create number range
if l > r then l, r = r, l end; -- smallest num first?
local t = {};
for i = l, r do t[#t+1] = i end;
return (table.unpack or unpack)(t);
end
end
-- set the metatable
setmetatable( 0, m );
Additional question: Is there any way for me to populate a ... value by value (to remove the need for a table & unpack in the example above)?
Your idea can be implemented using __call metamethod:
local mt = debug.getmetatable(0) or {}
mt.__call = function(a,b) -- a, b - positive integer numbers
return (('0'):rep(a-1)..('1'):rep(b-a+1)):match(('()1'):rep(b-a+1))
end
debug.setmetatable(0, mt)
-- Example:
print((3)(5)) --> 3 4 5

Resources