Using pair/ipair to simplify a lua function - lua

I have the following code that works:
function group1color()
for _, roomid in ipairs(group1rooms) do
if roomid == '1+' then
Controls.room1background.Color = '#dba643'
end
if roomid == '2+' then
Controls.room2background.Color = '#dba643'
end
if roomid == '3+' then
Controls.room3background.Color = '#dba643'
end
end
end
However, I need to copy the roomid if statement 5 more times, and then copy the function 8 times for eight different room groups. I am trying to figure out if there is a way to simplify this using pairs or ipairs? I am mainly looking for suggestions on how to simplify the iterations in the function.

You can access global variable by _G["varname"]
function groupcolor()
for N = 1, 8 do
local groupNrooms = _G["group"..N.."rooms"]
for _, roomid in ipairs(groupNrooms) do
local M = roomid:match"^(%d+)%+$"
if M then
Controls["room"..M.."background"].Color = '#dba643'
end
end
end
end

Related

Lua finding matching value's from 2 different tables and printing it

local Table1 = {"Test"}
local Table2 = {"'Test' = 'True'"}
--my friend showed me this
local Matched = {}
function has_same()
for _,v in pairs(Table1) do
for _,z in pairs(Table2) do
if v == z then table.insert(Matched, v)
end
end
end
end
has_same()
for i,v in pairs(Matched) do
print(v)
end
This is the code I've been trying to use and when I run it just comes up as blank
I am trying to make it so it prints the Test = True If this needs more explanation let me know

How can I handle with duplicate items in Aerospike script

I have script, its work properly, but I have to update it. Script now add items without any checking for existing.
function put_page(rec, id, val)
local l = rec['h']
if l==nil then l = list() rec['id'] = id end
list.append(l, val)
rec['h'] = l
if aerospike:exists(rec) then aerospike:update(rec) else aerospike:create(rec) end
end
I try iterate over list with for value in list.iterator(l) and append item if value~=val, but it didnt work.
ID in function is solr document_id, val is users_id. I get example object from aerospike: (('contextChannel', 'ContextChannel', None, bytearray(b'E\xfb\xa3\xd0\r\xd6\r\J#f\xa8\xf6>y!\xd18=\x9b')), {'ttl': 2592000, 'gen': 8}, {'id': 'ALKSD4EW', 'h': []})
UPDATE
I try different variants, and this is worked:
function put_page(rec, id, val)
local l = rec['h']
local count = 0
if l==nil then l = list() rec['id'] = id end
for value in list.iterator(l) do
if (value ~= val) then count = count + 1 end
end
if (list.size(l) == count) then list.append(l, val) end
rec['h'] = l
if aerospike:exists(rec) then aerospike:update(rec) else aerospike:create(rec) end
end
Don't create a UDF for something that exists as a List API operation. UDFs will not perform as well, nor scale as well.
You can do this without a UDF. Here's an example of doing the same thing using the Python client.
from aerospike_helpers.operations import list_operations as lh
from aerospike_helpers.operations import operations as oh
list_policy = {
"list_order": aerospike.LIST_UNORDERED,
"write_flags": (aerospike.LIST_WRITE_ADD_UNIQUE |
aerospike.LIST_WRITE_NO_FAIL)
}
ops = [
oh.write('id', id),
lh.list_append('h', val, list_policy)
]
client.operate(key, ops)
I have an example of a similar thing at rbotzer/aerospike-cdt-examples.

Lua: Merge 2 strings collections in a case-insensitive manner

I want to merge two strings collections in a case-insensitive manner:
string_collection1 = {"hello","buddy","world","ciao"}
string_collection2 = {"Hello","Buddy","holly","Bye", "bYe"}
merged_string_collection = merge_case_insensitive(string_collection1,string_collection2) --> {"hello","buddy","world","holly","bye","ciao"}
Here's an attempt, but it does not work...
function merge_case_insensitive(t1,t2)
t3 = {}
for _,s1 in pairs(t1) do
for _,s2 in pairs(t2) do
if string.lower(s1) == string.lower(s2) then
t3[s1] = s1
end
end
end
t4 = {}
i = 1
for s,_ in pairs(t3) do
t4[i] = string.lower(s)
i = i + 1
end
return t4
end
string_collection1 = {"hello","buddy","world","ciao"}
string_collection2 = {"Hello","Buddy","holly","Bye", "bYe"}
merged_string_collection = merge_case_insensitive(string_collection1,string_collection2)
for k,v in pairs(merged_string_collection) do print(k,v) end
It does not work because you use == to compare both strings which is case-sensitive.
You could do something like string.lower(s1) == string.lower(s2) to fix that.
Edit:
As you can't figure out the rest yourself, here's some code:
local t1 = {"hello","buddy","world","ciao"}
local t2 = {"Hello","Buddy","holly","Bye", "bYe"}
local aux_table = {}
local merged_table = {}
for k,v in pairs(t1) do
aux_table[v:lower()] = true
end
for k,v in pairs(t2) do
aux_table[v:lower()] = true
end
for k,v in pairs(aux_table) do
table.insert(merged_table, k)
end
merged_table now contains the lower case version of every word in both input tables.
Now pour that into a function that takes any number of input tables and you are done.
What we did here: we use the lower case version of every word in those tables and store them in a list. aux_table[string.lower("Hello")] will index the same value as aux_table[string.lower("hello")]. So we end up with one entry for each word, even if a word comes in multiple variations.
Using the keys saves us the hassle of comparing strings and distiguishing between unique words and others.
To get a table with all strings from two other tables appearing once (without regard to case), you need something like this:
function merge_case_insensitive(t1,t2)
local ans = {}
for _,v in pairs(t1) do ans[v:lower()] = true end
for _,v in pairs(t2) do ans[v:lower()] = true end
return ans
end
string_collection1 = {"hello","buddy","world","ciao"}
string_collection2 = {"Hello","Buddy","holly","Bye", "bYe"}
merged_string_collection = merge_case_insensitive(string_collection1,string_collection2)
for k in pairs(merged_string_collection) do print(k) end
Edit: And in case you want an array result (without adding another iteration)
function merge_case_insensitive(t1,t2)
local ans = {}
local
function add(t)
for _,v in pairs(t) do
v = v:lower()
if ans[v] == nil then ans[#ans+1] = v end
ans[v] = true
end
end
add(t1)
add(t2)
return ans
end
string_collection1 = {"hello","buddy","world","ciao"}
string_collection2 = {"Hello","Buddy","holly","Bye", "bYe"}
merged_string_collection = merge_case_insensitive(string_collection1,string_collection2)
for _,v in ipairs(merged_string_collection) do print(v) end
We can do this by simply iterations over both tables, and storing a temporary dictionary for checking what words we have already found, and if not there yet, putting them in our new array:
function Merge(t1, t2)
local found = {} --Temporary dictionary
local new = {} --New array
local low --Value to store low versions of words in later
for i,v in ipairs(t1) do --Begin iterating over table one
low = v:lower()
if not found[low] then --If not found yet
new[#new+1] = low --Put it in the new table
found[low] = true --Add it to found
end
end
for i,v in ipairs(t2) do --Repeat with table 2
low = v:lower()
if not found[low] then
new[#new+1] = low
found[low] = true
end
end
return new --Return the new array
end
This method eliminates the need for a third iteration, like in Piglet's answer, and doesn't keep redefining a function and closure and calling them like in tonypdmtr's answer.

Can't figure out this table arrangement

--The view of the table
local originalStats = {
Info = {Visit = false, Name = "None", Characters = 1},
Stats = {Levels = 0, XP = 0, XP2 = 75, Silver = 95},
Inventory = {
Hats = {"NoobHat"},
Robes = {"NoobRobe"},
Boots = {"NoobBoot"},
Weapons = {"NoobSword"}
}
}
local tempData = {}
--The arrangement here
function Module:ReadAll(player)
for k,v in pairs(tempData[player]) do
if type(v) == 'table' then
for k2, v2 in pairs(v) do
print(k2) print(v2)
if type(v2) == 'table' then
for k3, v3 in pairs(v2) do
print(k3) print(v3)
end
else
print(k2) print(v2)
end
end
else
print(k) print(v)
end
end
end
I'm sorry, but I can't seem to figure out how to arrange this 'ReadAll' function to where It'll show all the correct stats in the right orders.
The output is something like this:
Boots
table: 1A73CF10
1
NoobBoot
Weapons
table: 1A7427F0
1
NoobSword
Robes
table: 1A743D50
1
NoobRobe
Hats
table: 1A73C9D0
1
NoobHat
XP2
75
XP2
75
Levels
2
Levels
2
XP
0
XP
0
Here's a way to print all the elements without double or table reference values showing up.
As the name states, this function will print all the elements within a table, no matter how many nested tables there are inside it. I don't have a way to order them at the moment, but I'll update my answer if I find a way. You can also get rid of the empty spaces in the print line, I just used it so it would look neater. Let me know if it works.
function allElementsInTable(table)
for k,v in pairs(table) do
if type(table[k]) == 'table' then
print(k .. ":")
allElementsInTable(v)
else
print(" " .. k .. " = " .. tostring(v))
end
end
end
--place the name of your table in the parameter for this function
allElementsInTable(originalStats)
After more experimenting, I got this, if anyone wants it, feel free to use it.
tempData = { Info = {Visit = false, Name = 'None'},
Stats = {LVL = 0, XP = 0, Silver = 75},
Inventory = { Armors = {'BasicArmor'},
Weapons = {'BasicSword'} }
}
function Read()
for i, v in pairs(tempData['Info']) do
print(i..'\t',v)
end
----------
for i2, v2 in pairs(tempData['Stats']) do
print(i2..'\t',v2)
end
----------
for i3, v3 in pairs(tempData['Inventory']) do
print(i3..':')
for i4, v4 in pairs(v3) do
print('\t',v4)
end
end
end
Read()
Don't expect table's fields to be iterated with pairs() in some specific order. Internally Lua tables are hashtables, and the order of fields in it is not specified at all. It will change between runs, you can't have them iterated in the same order as they were filled.Only arrays with consecutive integer indices will maintain the order of their elements.

Count number of occurrences of a value in Lua table

Basically what I want to do is convert a table of this format
result={{id="abcd",dmg=1},{id="abcd",dmg=1},{id="abcd",dmg=1}}
to a table of this format:
result={{id="abcd",dmg=1, qty=3}}
so I need to know how many times does {id="abcd",dmg=1} occur in the table. Does anybody know a better way of doing this than just nested for loops?
result={{id="abcd",dmg=1},{id="defg",dmg=2},{id="abcd",dmg=1},{id="abcd",dmg=1}}
local t, old_result = {}, result
result = {}
for _, v in ipairs(old_result) do
local h = v.id..'\0'..v.dmg
v = t[h] or table.insert(result, v) or v
t[h], v.qty = v, (v.qty or 0) + 1
end
-- result: {{id="abcd",dmg=1,qty=3},{id="defg",dmg=2,qty=1}}
So you want to clear duplicate contents, although a better solution is to not let dupe contents in, here you go:
function Originals(parent)
local originals = {}
for i,object in ipairs(parent) do
for ii,orig in ipairs(originals) do
local dupe = true
for key, val in pairs(object) do
if val ~= orig[key] then
dupe = false
break
end
end
if not dupe then
originals[#originals+1] = object
end
end
return originals
end
I tried to make the code self explanatory, but the general idea is that it loops through and puts all the objects with new contents aside, and returns them after.
Warning: Code Untested

Resources