How can I handle with duplicate items in Aerospike script - lua

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.

Related

Using pair/ipair to simplify a lua function

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

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

Remove duplicates from LUA Table by timestamp

I was on stack a few days back for help inserting records to prevent duplicates. However the process to enter these is slow and they slip in.
I have a user base of about 10,000 players, and they have duplicate entries.. I've been trying to filter out these duplicates without success. The examples on stack have no panned out for me.
Here is a clip from my table
[18] =
{
["soldAmount"] = 25,
["buyer"] = [[#playername]],
["timestampz"] = 1398004426,
["secsSinceEvent"] = 55051,
["guildName"] = [[TradingGuild]],
["eventType"] = 15,
["seller"] = [[#myname]],
},
[19] =
{
["soldAmount"] = 25,
["buyer"] = [[#playername]],
["timestampz"] = 1398004426,
["secsSinceEvent"] = 55051,
["guildName"] = [[TradingGuild]],
["eventType"] = 15,
["seller"] = [[#myname]],
},
The timestamp's match and they should not have been added.
for k,v in pairs(sellHistory) do mSavedTHVars.Forever_Sales[k] = v
if mSavedTHVars.Forever_Sales.timestampz ~= sellHistory.timestampz then
table.insert(mSavedTHVars.Forever_Sales, sellHistory)
end end
Now, I need to find out how to remove the current duplicates, and here is what I've tried.
function table_unique(tt)
local newtable = {}
for ii,xx in ipairs(tt) do
if table_count(newtable.timestampz, xx) ~= tt.timestampz then
newtable[#newtable+1] = xx
end
end
return newtable
end
I hope this information provided was clean and understandable.
Thanks!
UPDATE
Attempt #20 ;)
for k,v in pairs(mSavedTHVars.Forever_Sales) do
if v == mSavedTHVars.Forever_Sales.timestampz then
table.remove(mSavedTHVars.Forever_Sales,k)
end
end
No luck yet.
UPDATE
This has worked
for k,v in pairs(mSavedTHVars.Forever_Sales) do mSavedTHVars.Forever_Sales[k] = v
if v.timestampz == mSavedTHVars.Forever_Sales.timestampz then
table.remove(mSavedTHVars.Forever_Sales, k)
end
end
IS this a good approach?
Assuming that mSavedTHVars.Forever_Sales[18] and mSavedTHVars.Forever_Sales[19] are the tables you listed in your post, then to remove all duplicates based on same time stamp it is easiest to create a "set" based on timestamp (since the timestamp is your condition for uniqueness). Loop through your mSavedTHVars.Forever_Sales and for each item, add item to new table only if its timestamp not already in set:
function removeDuplicates(tbl)
local timestamps = {}
local newTable = {}
for index, record in ipairs(tbl) do
if timestamps[record.timestampz] == nil then
timestamps[record.timestampz] = 1
table.insert(newTable, record)
end
end
return newTable
end
mSavedTHVars.Forever_Sales = removeDuplicates(mSavedTHVars.Forever_Sales)
Update based on Question Update:
My comment on following proposed solution:
for k,v in pairs(mSavedTHVars.Forever_Sales) do
mSavedTHVars.Forever_Sales[k] = v
if v.timestampz == mSavedTHVars.Forever_Sales.timestampz then
table.remove(mSavedTHVars.Forever_Sales, k)
end
end
The problem is that I don't see how that can work. When you do for k,v in pairs(mSavedTHVars.Forever_Sales) do then v is mSavedTHVars.Forever_Sales[k] so the next line mSavedTHVars.Forever_Sales[k] = v does nothing. Then if v.timestampz == mSavedTHVars.Forever_Sales.timestampz compares the timestamp of v, i.e. of mSavedTHVars.Forever_Sales[k], with value of a timestampz field in mSavedTHVars.Forever_Sales. But latter is a table without such field, so right-hand-side of == will be nil, so the condition will only be true if v.timestampz is nil, which I don't think is ever the case.
The main reason that I used a solution of creating new table instead of removing duplicates from the existing table is that you can edit a table while iterating over it with pairs or ipairs. If you were to use a reverse counter, it would probably be ok (but I have not tested, test to be sure):
function removeDuplicates(tbl)
local timestamps = {}
local numItems = #tbl
for index=numItems, 1, -1, do
local record = tbl[index]
if timestamps[record.timestampz] ~= nil then
table.remove(newTable, index)
end
timestamps[record.timestampz] = 1
end
end
Also I think the intent of the function is not as clear, but maybe this is just personal preference.

How to find sequential items in an array using lua?

I need a piece of code in lua language that can find sequential items in an array that the number of item in the group exceeds a specific nubmer. Example:if I have the array(the numbers won't be in the right order, randomly distributed)->( 2,5,9,10,11,21,23,15,14,12,22,13,24 ) ; there are two sequential groups (9,10,11,12,13,14,15) and (21,22,23,24 ) . I want the first group to be found if the specific number say (4) or more, or I can get the two groups if the number is (3) or less for example.
thanks
The logical way would seem to be to reorder the table and look for gaps in the sequences.
function table.copy(t)
local t2 = {}
for k,v in pairs(t) do
t2[k] = v
end
return t2
end
function groups(org, cnt)
-- Returns a table containing tables containing the groups found
local res = {}
local group = {}
tbl = table.copy(org) -- Prevent reordering of Original Table
table.sort(tbl)
local last = nil
for _,val in ipairs(tbl) do
if last and last + 1 ~= val then
if #group >= cnt then
table.insert(res,group)
end
group = {}
end
table.insert(group,val)
last = val
end
if #group >= cnt then
table.insert(res,group)
end
return res
end
local org = { 2,5,9,10,11,21,23,15,14,12,22,13,24 }
local result = groups(org,3)
print('Number of Groups',#result)

Resources