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^"
Related
So I need to write a program which gets a table as an input and gives the same table as an output without the values with even keys. So basically I need to filter out the even keys and their values and leave the uneven keys with their values.
local function selecteer_oneven(tabel)
for q, n in ipairs(tabel) do
if (q % 2) == 0 then
table.remove(tabel, q)
end
end
return tabel
end
local function printtabel(tabel)
for k,v in pairs(tabel) do
print(k,v)
end
end
io.write("Geef een lua-tabel: ")
local tabelstring = "t = "..io.read()
local string2tab = loadstring(tabelstring)
string2tab()
local resultaat = selecteer_oneven(t)
printtabel(resultaat)
my input is
{ "aap", "kat", "hond", "paard", "kip", "salamander", "programmeren is leuk" }
and my output is
1 aap
2 hond
3 paard
4 salamander
5 programmeren is leuk
(sorry it is in Dutch)
"Aap", "Hond", "Programmeren is leuk" are the only uneven ones. "paard", and "salamander" are even.
Dont do table.remove on the table you are checking at same time.
Better do a second local table and insert q.
And finaly return the second table...
local function selecteer_oneven(tabel)
local tabel2={}
for q, n in ipairs(tabel) do
if (q % 2) ~= 0 then
table.insert(tabel2, q)
end
end
return tabel2
end
...dont tested - yet ;-)
EDIT: Tested with lua -i
-- <ready>
>function selecteer_oneven(tabel)
local tabel2={}
for q, n in ipairs(tabel) do
if (q % 2) ~= 0 then
table.insert(tabel2, q)
end
end
return tabel2
end
-- <ready>
>dump(selecteer_oneven({1,2,3,4,5,6,7,8,9,10}))
1=1
2=3
3=5
4=7
5=9
-- <ready>
>-- whats dump?
-- <ready>
>code.dump
-- dump()
return function(dump)
for key,value in pairs(dump) do
io.write(string.format("%s=%s\n",key,value))
end
end
-- <ready>
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
local t = "{{2173,1},{2160,5}}"
print(#t) -- 19?? wrong
How to convert to appear in numbers?
local t = {{2173,1},{2160,5}}
print(#t) -- 2 correct
You can run the string through load or loadstring (depending on your Lua version), which will return the table you are looking for:
local t = "{{2173,1},{2160,5}}"
t = (loadstring or load)("return "..t)()
print(#t) -- 2
Here is an ad hoc solution for the input you gave:
local s = "{{2173,1},{2160,5}}"
local t = {}
local n = 0
for a,b in s:gmatch("(%d+),(%d+)") do
n = n + 1
t[n] = {a,b}
end
for k,v in ipairs(t) do print(k,v[1],v[2]) end
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
Is there a way to use the arg 2 value of table.concat to represent the current table index?
eg:
t = {}
t[1] = "a"
t[2] = "b"
t[3] = "c"
X = table.concat(t,"\n")
desired output of table concat (X):
"1 a\n2 b\n3 c\n"
Simple answer : no.
table.concat is something really basic, and really fast.
So you should do it in a loop anyhow.
If you want to avoid excessive string concatenation you can do:
function concatIndexed(tab,template)
template = template or '%d %s\n'
local tt = {}
for k,v in ipairs(tab) do
tt[#tt+1]=template:format(k,v)
end
return table.concat(tt)
end
X = concatIndexed(t) -- and optionally specify a certain per item format
Y = concatIndexed(t,'custom format %3d %s\n')
I don't think so: how would you tell it that the separator between keys and values is supposed to be a space, for example?
You can write a general mapping function to do what you'd like:
function map2(t, func)
local out = {}
for k, v in pairs(t) do
out[k] = func(k, v)
end
return out
end
function joinbyspace(k, v)
return k .. ' ' .. v
end
X = table.concat(map2(t, joinbyspace), "\n")
No. But there is a work around:
local n = 0
local function next_line_no()
n = n + 1
return n..' '
end
X = table.concat(t,'\0'):gsub('%f[%Z]',next_line_no):gsub('%z','\n')
function Util_Concat(tab, seperator)
if seperator == nil then return table.concat(tab) end
local buffer = {}
for i, v in ipairs(tab) do
buffer[#buffer + 1] = v
if i < #tab then
buffer[#buffer + 1] = seperator
end
end
return table.concat(buffer)
end
usage tab is where the table input is and seperator be both nil or string (if it nil it act like ordinary table.concat)
print(Util_Concat({"Hello", "World"}, "_"))
--Prints
--Hello_world