So, i have a script where i am inputting 3 words in a string and putting them into a small table and i only need this script to print a new table i can copy and paste, so i just need to print what the table would look like this is the script currently have
local tbl = {
{1, "", 0},
{2, "", 0},
{3, "", 0}
}
local input = "i hate debugging"
local words = {}
x = 0
repeat
x = x + 1
for i, v in ipairs(tbl) do
if tonumber(v[1]) == x then
for word in input:gmatch"[^ ,\r\n]+" do
table.insert(words, word)
end
end
end
until x == 1
and the desired output should look like this
{1, "i", 0},
{2, "hate", 0},
{3, "debugging", 0},
The question isn't very clear, and OP goal is not clear, but it seems that you may want something like this:
local tbl = {
{ 1, "", 0 },
{ 2, "", 0 },
{ 3, "", 0 }
}
local input = "i hate debugging"
local nextWord = input:gmatch"[^ ,\r\n]+"
for k, t in ipairs(tbl) do
t[2] = nextWord() or ""
end
-- Display updated `tbl`
print("updated tbl")
for k, v in ipairs(tbl) do
print(string.format('{ %d, "%s", %d },', v[1], v[2], v[3]))
end
gmatch returns an iterator, so you can just call this iterator repeatedly to get successive matches. You can loop over tbl, calling the iterator each time to set the string. When the iterator is out of matches it will return nil, so the code sets the string to "" when the iterator is exhausted.
Program output:
updated tbl
{ 1, "i", 0 },
{ 2, "hate", 0 },
{ 3, "debugging", 0 },
Creating A New Table From Input
OP has clarified in a comment that a new table should be created from the input. Here is a function createWordTable that creates and returns a fresh table from a string of words. The printWordTable function is just a utility function to show the contents of a word table.
function createWordTable(wordString)
local wordTbl = {}
local i = 1
for w in wordString:gmatch"[^ ,\r\n]+" do
wordTbl[i] = { i, w, 0 }
i = i + 1
end
return wordTbl
end
function printWordTable(wordTbl)
for k, v in ipairs(wordTbl) do
print(string.format('{ %d, %s, %d }', v[1], v[2], v[3]))
end
end
Sample interaction:
> wtbl = createWordTable("one, two, three")
> printWordTable(wtbl)
{ 1, one, 0 }
{ 2, two, 0 }
{ 3, three, 0 }
> wtbl = createWordTable("one, two, three, four, five")
> printWordTable(wtbl)
{ 1, one, 0 }
{ 2, two, 0 }
{ 3, three, 0 }
{ 4, four, 0 }
{ 5, five, 0 }
Related
local seq = { 1, 2, 3, 4, 5 } -- obviously, it's a sequence.
local non_seq = { 1, 2, 3, nil, 5 } -- but it's not.
The defination about sequence: The Length Operator
This question is in chapter 5 of Programming in Lua 4st.
Any comments I would greatly appreciate
You linked the information you need for your answer.
A border in Lua 5.3 is defined as:
(border == 0 or t[border] ~= nil) and t[border + 1] == nil
A proper sequence can only contain one border. However to cover some other condition the code does require a bit more leg work, such as validating the index can be in a sequence.
function is_sequence(t)
local borders = 0
if t[1] ~= nil then -- all sequences must start at 1.
for index in pairs(t) do
if natural_index(index) and t[index + 1] == nil then
borders = borders + 1
if borders > 1 then
break
end
end
end
end
return borders == 1 or valid_no_borders(t) and borders == 0
end
function natural_index(index)
return type(index) == "number" and index > 0 and math.floor(index) == index
end
function valid_no_borders(t)
result = true
for k in pairs(t) do
if natural_index(k) then
result = false
break
end
end
return t[1] == nil and result
end
-- Tests
local seqs = {
{ 1, 2, 3, 4, 5 }, -- obviously, it's a sequence.
{ 1, 2, 3, 4, ["potato"] = 5 },
{ 1, 2, [3.3] = 3 },
{ [2.2] = 2 },
{ [-1] = -1, [0] = 0, 1, 2, 3 },
{},
}
for _, v in ipairs(seqs) do
print("seq: ", is_sequence(v))
end
local non_seqs ={
{ 1, 2, 3, nil, 5 }, -- but it's not.
{ [2] = 2 },
}
for _, v in ipairs(non_seqs) do
print("non_seq: ", is_sequence(v))
end
Results
seq: true
seq: true
seq: true
seq: true
seq: true
seq: true
non_seq: false
non_seq: false
This method has the benefit of only evaluating each element once and exiting as early as possible if the table is not a valid sequence.
There might be a better way, but the first thing I could come up with would look something like this:
local function sequence(tab)
local border
for index in ipairs(tab) do
border = index
end
for index in pairs(tab) do
if type(index)=="number" and index > border then
return false
end
end
end
The problem is that you need to iterate over the table twice; the first time up to the first border, then either until the first integer key larger than the first border, or through the entire table if it is indeed a sequence.
As #Nifim pointed out, you can also implement the definition directly. A slightly improved version of their answer:
local function natural(value)
return type(value)=="number" and value >= 1 and value % 1 == 0
end
local function sequence(tab)
-- 0 can be a border even when it's nil
if tab[1] == nil then
for index in pairs(tab) do
if natural(index) then
return false
end
end
else
local border = false
for index in pairs(tab) do
if natural(index) and tab[index+1]==nil then
if border then
return false
else
border = true
end
end
end
end
return true
end
All you need to do is check if the array part of the table has any holes.
local function isSequence(t)
for k in pairs(t) do
-- Is k an integer greater than 1 whose previous value is nil?
if
type(k) == 'number' and k == math.floor(k) and k > 1 and t[k - 1] == nil
then
return false
end
end
return true
end
If you detect an integer key greater than 1 whose previous value is nil, then the table must have at least 2 borders, making it an invalid sequence. One is somewhere between 0 and that key, and the other is somewhere after that key.
how can I use "for k, j in pairs() do" for 2 arrays in lua?
local blipmarker1 = {
{ x = 10 , y = 5, z = 3 },
{ x = 5, y = 5, z= 3}
}
local blipmarker2 = {
{ x = 100, y= 150, z=30 }
}
function createtext(){
local pos = GetEntityCoords(PlayerPedId(), true)
for k, j in pairs(blipmarker1,blimarker2) do
draw3DText(pos.x, pos.y, pos.z, j.x, j.y, j.z)
end
}
Function pairs() accepts only one argument of type table. You need a loop for each table:
for k,j in pairs(blipmarker1) do
...
end
for k,j in pairs(blipmarker2) do
...
end
You could write your own stateful multipairs iterator. Consult Chapter 9.3 “Coroutines as Iterators” of Programming in Lua for more details: https://www.lua.org/pil/9.3.html
local function multipairs(tables)
return coroutine.wrap(function()
for _, t in pairs(tables) do -- Maybe you want ipairs here
for k, v in pairs(t) do
coroutine.yield(k, v)
end
end
end)
end
local blipmarker1 = {
{ x = 10 , y = 5, z = 3 },
{ x = 5, y = 5, z= 3}
}
local blipmarker2 = {
{ x = 100, y= 150, z=30 }
}
for _, j in multipairs{blipmarker1, blipmarker2} do
print(j.x, j.y, j.z)
end
function table_merge(t1, t2)
for _, v in ipairs(t2) do
table.insert(t1, v)
end
end
function getMaster(tbl, rules)
local result = false
for _, rule in ipairs(rules) do
for i, v in ipairs(tbl) do
result = v
if tostring(v) ~= tostring(rule) then
result = false
break
end
end
if result then break end
end
return result
end
function start(data, rules)
local master_key, master_val
local _temp, continue = {}, true
for i, tbl in ipairs(data) do
local master = getMaster(tbl, rules)
if master and master ~= master_val then
continue = true
end
if continue then
if master then
master_key = i
master_val = master
elseif tbl[#tbl] == master_val then
tbl[#tbl] = nil
table.insert(_temp[master_key], master_val)
elseif master_key then
continue = false
end
end
_temp[i] = tbl
end
local result = {}
for i, tbl in ipairs(_temp) do
table_merge(result, tbl)
end
return table.concat(result, "")
end
-- RULES
local rules = { 0, 1}
local data = {
{ 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 0 },
{ 0, 0, 0, 8, 1, 0 },
{ 1, 1, 1, 1, 8, 8 },
{ 0, 0, 0, 0, 0, 0 },
}
start(data, rules)
OUTPUT:
000000001111100081111188000000
The expected results should be this:
000000001111110008111188000000
How do I achieve the required results? the table can contain more than six elements but initially it is six. so when all the elements are 1, it will check the next immediate Table to see if the last element is also one; if true it removes it and adds to the six making seven, it will then check again for the next immediate table if the last digit is 1, if true it removes that also and adds to the seven making 8. It will check again and if false return to where it left. So here the table whose element were removed become five in number.
So I was hoping that they could satisfy the rule also if all the five elemnts are 1 or 0. But it seems only the six elements satisfy the rule...
I hope it's clear Thanks
function table_merge(t1, t2)
for _, v in ipairs(t2) do
table.insert(t1, v)
end
end
function getMaster(tbl, rules, w)
local result = false
for _, rule in ipairs(rules) do
for i = 1, w do
local v = tbl[i]
result = v
if tostring(v) ~= tostring(rule) then
result = false
break
end
end
if result then break end
end
return result
end
function start(data, rules)
local width = #data[1] -- assuming all data rows have the same width
local master_keys = {}
local master_values = {}
local continue_idx = width + 1
for i, tbl in ipairs(data) do
for w = width, 1, -1 do
if w >= continue_idx and tbl[w] == master_values[w] then
table.insert(data[master_keys[w]], master_values[w])
tbl[w] = nil
else
local master = getMaster(tbl, rules, w)
if master then
master_keys[w] = i
master_values[w] = master
continue_idx = w
else
continue_idx = w + 1
end
break
end
end
end
local result = {}
for i, tbl in ipairs(data) do
table_merge(result, tbl)
end
return table.concat(result, "")
end
-- RULES
local rules = { 0, 1 }
local data = {
{ 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 0 },
{ 0, 0, 0, 8, 1, 0 },
{ 1, 1, 1, 1, 8, 8 },
{ 0, 0, 0, 0, 0, 0 },
}
print(start(data, rules))
I want to be able to map functions that take multiple arguments like
function(a, b) return a+b end
onto a table so that I can write stuff like
answer = varmap(function(a, b) return a+b end, {1, 7, 3}, {5, 4, 8}
but I am not comfortable with lua varargs and the code samples on wikibooks use table.getn, and when you replace them with # it doesn't work and returns "attempt to preform arithmatic on local 'a' (a nil value)"
One more possibility:
local unpack = table.unpack or unpack
--------------------------------------------------------------------------------
-- Python-like zip() iterator
--------------------------------------------------------------------------------
function zip(...)
local arrays, ans = {...}, {}
local index = 0
return
function()
index = index + 1
for i,t in ipairs(arrays) do
if type(t) == 'function' then ans[i] = t() else ans[i] = t[index] end
if ans[i] == nil then return end
end
return ans
end
end
--------------------------------------------------------------------------------
function map(f,...)
assert(type(f) == 'function','Function expected for 1st arg')
local t = {...}
return coroutine.wrap(
function()
for t in zip(unpack(t)) do
coroutine.yield(f(unpack(t)))
end
end)
end
--------------------------------------------------------------------------------
-- Example use
for item in map(function(a, b) return a+b end, {1, 7, 3}, {5, 4, 8}) do
print(item)
end
print()
for item in map(function(a) return a*2 end, {1, 7, 3}) do
print(item)
end
local function imap(func, ...) -- imap(func, src_table_1, src_table_2, ...)
local result = {}
local src_tables_arr = {...}
if #src_tables_arr == 1 then
for k, v in ipairs(src_tables_arr[1]) do
result[k] = func(v)
end
else
for k = 1, #src_tables_arr[1] do
result[k] = func(
(table.unpack or unpack)
(
imap(
function(src_t) return src_t[k] end,
src_tables_arr
)
)
)
end
end
return result
end
table.imap = imap
Usage:
local arr = table.imap(function (a, b) return a+b end, {1, 7, 3}, {5, 4, 8})
Perhaps you are looking for something like this:
function varmapn(func, ...)
local args, result = { ... }, {}
for arg_i = 1, #(args[1]) do
local call_args = {}
for arg_list = 1, #args do
table.insert(call_args, args[arg_list][arg_i])
end
table.insert(result, func(table.unpack(call_args)))
end
return result
end
Sample interaction:
> answer = varmapn(function (a, b) return a+b end, {1, 7, 3}, {5, 4, 8})
> print(answer)
table: 0x970eb0
> for i = 1, 3 do print(answer[i]) end
6
11
11
Or, here is a slightly more involved function that is more general. For argument lists it takes arrays, or it takes tables with arbitrary keys:
function mapn(func, ...)
local args, call_args = { ... }, {}
local result = {}
for k in pairs(args[1]) do
call_args[k] = {}
end
for arg_list, v in pairs(args) do
for k in pairs(args[1]) do
table.insert(call_args[k], v[k])
end
end
for k, v in pairs(call_args) do
result[k] = func(table.unpack(v))
end
return result
end
Sample interaction:
> answer = mapn(function (a, b) return a+b end, {x=1, y=7, z=3}, {x=5, y=4, z=8})
> for k,v in pairs(answer) do print(k .. " = " .. v) end
z = 11
y = 11
x = 6
> answer = mapn(function (a, b) return a+b end, {1, 7, 3}, {5, 4, 8})
> for i = 1, 3 do print(answer[i]) end
6
11
11
I am trying to learn how to print strings from a value in a table. For example.
TestTable = { "Apples" = 0, "Oranges" = 1, "Grapes" = 1, "Bananas" = 0}
for i=1, #TestTable do
if TestTable[i] == 1 then
print(TestTable[i]) --> Oranges Grapes
end
end
Not sure if that made sense, but I want to print all the strings with the 1 value.
Unless the __len metamethod is defined, the # operator can only be used on a sequence, but TestTable is not one.
You can use pairs to iterate the table:
TestTable = { Apples = 0, Oranges = 1, Grapes = 1, Bananas = 0}
for k, v in pairs(TestTable) do
if v == 1 then
print(k)
end
end