How to redefine values in inner tables? - recursion

Basically, scan the entire table for values of type say booleans for example and change them into a string, must work for inner tables and dictionaries...
local Table = {
String = "abc",
Number = 123,
Boolean = true,
InnerTable = {
Boolean2 = false,
InnerInnerTable = {
Boolean3 = true,
InnerInnerInnerTable = {
-- And so on...
}
}
}
}
In this example I want to change every boolean in the table to a string like "true" but without knowing what the table looks like, what I need is a function for any table parsed to be edited (dictionary or not). I couldn't accomplish this with a for loop or custom recursive functions so I need help.

What you need is a simple traversal of the table structure which maps booleans to strings. This can be implemented recursively as follows:
local function deep_bool_to_string(tab)
for k, v in pairs(tab) do
if type(v) == "boolean" then
tab[k] = tostring(v)
elseif type(v) == "table" then
deep_bool_to_string(v)
end
end
end
Usage in your example: deep_bool_to_string(Table). Mutates Table.
Note that this only recursively dives into values, not keys of tables, as the latter isn't well defined: Should {["true"] = 1, [true] = 2} become {["true"] = 1} or {["true"] = 2}?
In its current form, this function has two limitations:
A circular table structure will cause it to overflow the stack.
A too deeply nested table structure may do the same.
(1) can be fixed by keeping track of already converted tables:
local deep_bool_to_string = function(tab)
local seen = {} -- "Set" of seen tables
local function convert(t)
seen[t] = true
for k, v in pairs(t) do
if type(v) == "boolean" then
t[k] = tostring(v)
elseif type(v) == "table" and not seen[v] then
convert(v)
end
end
end
convert(tab)
end
(2) can be fixed by implementing the traversal using a table-based "stack":
local deep_bool_to_string = function(tab)
local seen = {[tab] = true} -- "Set" of seen tables
local to_convert = {tab} -- "Stack" of tables to convert
repeat
local t = table.remove(to_convert) -- "pop" from stack
for k, v in pairs(t) do
if type(v) == "boolean" then
t[k] = tostring(v)
elseif type(v) == "table" and not seen[v] then -- new table found?
seen[v] = true
table.insert(to_convert, v) -- "push" on stack
end
end
until #to_convert == 0
end
All these are implementations of depth-first traversals, since they are usually more convenient to write (and more efficient) than breath-first traversals since they use a stack rather than a queue.

Related

Searching in database with scrambled words in SQLite

I am wondering if its possible to search in the database with the given scrambled words.
I have a mobs table in database and it holds the name of the monster names
If given monster name is A Golden Dregon or A Golden Dfigon or A Gelden Dragon I want it to find A Golden Dragon or with the matches that close to it from database. Usually one or two letters at max is given like this as scrambled.
Is that possible with just SQL queries? Or should I build the query by parsing the given monster name?
I am using LUA for the code side.
I have come to know this search type as a fuzzy search. I mainly program in JS and use fuse.js all the time for this kind of problem.
Fuzzy Searches are based on the Levenshtein algorithm that rate the distance of two strings. When you have this distance value you can sort or drop elements from a list based on the score.
I found the algorithm in lua here.
function levenshtein(s, t)
local s, t = tostring(s), tostring(t)
if type(s) == 'string' and type(t) == 'string' then
local m, n, d = #s, #t, {}
for i = 0, m do d[i] = { [0] = i } end
for j = 1, n do d[0][j] = j end
for i = 1, m do
for j = 1, n do
local cost = s:sub(i,i) == t:sub(j,j) and 0 or 1
d[i][j] = math.min(d[i-1][j]+1, d[i][j-1]+1, d[i-1][j-1]+cost)
end
end
return d[m][n]
end
end
As explained in the site you compare two strings like so and get a score based on the distance of them, then sort or drop the items being search based on the scores given. As this is CPU expensive I would suggest caching or use a memoize function to store common mistakes.
levenshtein('referrer', 'referrer') -- zero distance
>>> 0
levenshtein('referrer', 'referer') -- distance of one character
>>> 1
levenshtein('random', 'strings') -- random big distance
>>> 6
Got a simple version of it working in lua here I must say lua is an easy language to pick up and start coding with.
local monsters = {'A Golden Dragon', 'Goblins', 'Bunny', 'Dragoon'}
function levenshtein(s, t)
local s, t = tostring(s), tostring(t)
if type(s) == 'string' and type(t) == 'string' then
local m, n, d = #s, #t, {}
for i = 0, m do d[i] = { [0] = i } end
for j = 1, n do d[0][j] = j end
for i = 1, m do
for j = 1, n do
local cost = s:sub(i,i) == t:sub(j,j) and 0 or 1
d[i][j] = math.min(d[i-1][j]+1, d[i][j-1]+1, d[i-1][j-1]+cost)
end
end
return d[m][n]
end
end
--Fuzzy Search Returns the Best Match in a list
function fuzzySearch(list, searchText)
local bestMatch = nil;
local lowestScore = nil;
for i = 1, #list do
local score = levenshtein(list[i], searchText)
if lowestScore == nil or score < lowestScore then
bestMatch = list[i]
lowestScore = score
end
end
return bestMatch
end
print ( fuzzySearch(monsters, 'golen dragggon') )
print ( fuzzySearch(monsters, 'A Golden Dfigon') )
print ( fuzzySearch(monsters, 'A Gelden Dragon') )
print ( fuzzySearch(monsters, 'Dragooon') ) --should be Dragoon
print ( fuzzySearch(monsters, 'Funny') ) --should be Bunny
print ( fuzzySearch(monsters, 'Gob') ) --should be Goblins
Output
A Golden Dragon
A Golden Dragon
A Golden Dragon
Dragoon
Bunny
Goblins
For SQL
You can try to do this same algorithm in T-SQL as talked about here.
In SQLlite there is an extension called editdist3 which also uses this algorithm the docs are here.
I would be hard to compensate for all the different one and two letter scrambled combinations, but you could create a lua table of common misspellings of "A Golden Dragon" check if it is in the table. I have never used lua before but here is my best try at some sample code:
local mob_name = "A Golden Dregon"--you could do something like, input("Enter mob name:")
local scrambled_dragon_names = {"A Golden Dregon", "A Golden Dfigon", "A Gelden Dragon"}
for _,v in pairs(scrambled_dragon_names) do
if v == mob_name then
mob_name = "A Golden Dragon"
break
end
end
I really hope I have helped!
P.S. If you have anymore questions go ahead and comment and I will try to answer ASAP.
You will have to parse the given monster name to some extent, by making assumptions about how badly it is misspelled. For example, if the user supplied the name
b fulden gorgon
There is no way in hell you can get to "A Golden Dragon". However, if you assume that the user will always get the first and last letters of every word correctly, then you could parse the words in the given name to get the first and last letters of each word, which would give you
"A", "G" "n", "D" "n"
Then you could use the LIKE operator in your query, like so:
SELECT * FROM mobs WHERE monster_name LIKE 'A G%n D%n';
The main point here is what assumptions you make about the misspelling. The closer you can narrow it down, the better your query results will be.

Lua - writing iterator similar to ipairs, but selects indices

I'd like to write an iterator that behaves exactly like ipairs, except which takes a second argument. The second argument would be a table of the indices that ipairs should loop over.
I'm wondering if my current approach is inefficient, and how I could improve it with closures.
I'm also open to other methods of accomplishing the same thing. But I like iterators because they're easy to use and debug.
I'll be making references to and using some of the terminology from Programming in Lua (PiL), especially the chapter on closures (chapter 7 in the link).
So I'd like to have this,
ary = {10,20,30,40}
for i,v in selpairs(ary, {1,3}) do
ary[i] = v+5
print(string.format("ary[%d] is now = %g", i, ary[i]))
end
which would output this:
ary[1] is now = 15
ary[3] is now = 35
My current approach is this : (in order: iterator, factory, then generic for)
iter = function (t, s)
s = s + 1
local i = t.sel[s]
local v = t.ary[i]
if v then
return s, i, v
end
end
function selpairs (ary, sel)
local t = {}
t.ary = ary
t.sel = sel
return iter, t, 0
end
ary = {10,20,30,40}
for _,i,v in selpairs(ary, {1,3}) do
ary[i] = v+5
print(string.format("ary[%d] is now = %g", i, ary[i]))
end
-- same output as before
It works. sel is the array of 'selected' indices. ary is the array you want to perform the loop on. Inside iter, s indexes sel, and i indexes ary.
But there are a few glaring problems.
I must always discard the first returned argument s (_ in the for loop). I never need s, but it has to be returned as the first argument since it is the "control variable".
The "invariant state" is actually two invariant states (ary and sel) packed into a single table. Pil says that this is more expensive, and recommends using closures. (Hence my writing this question).
The rest can of this can be ignored. I'm just providing more context for what I'm wanting to use selpairs for.
I'm mostly concerned with the second problem. I'm writing this for a library I'm making for generating music. Doing simple stuff like ary[i] = v+5 won't really be a problem. But when I do stuff like accessing object properties and checking bounds, then I get concerned that the 'invariant state as a table' approach may be creating unnecessary overhead. Should I be concerned about this?
If anything, I'd like to know how to write this with closures just for the knowledge.
Of course, I've tried using closures, but I'm failing to understand the scope of "locals in enclosing functions" and how it relates to a for loop calling an iterator.
As for the first problem, I imagine I could make the control variable a table of s, i, and v. And at the return in iter, unpack the table in the desired order.
But I'm guessing that this is inefficient too.
Eventually, I'd like to write an iterator which does this, except nested into itself. My main data structure is arrays of arrays, so I'd hope to make something like this:
ary_of_arys = {
{10, 20, 30, 40},
{5, 6, 7, 8},
{0.9, 1, 1.1, 1.2},
}
for aoa,i,v in selpairs_inarrays(ary_of_arys, {1,3}, {2,3,4}) do
ary_of_arys[aoa][i] = v+5
end
And this too, could use the table approach, but it'd be nice to know how to take advantage of closures.
I've actually done something similar: A function that basically does the same thing by taking a function as it's fourth and final argument. It works just fine, but would this be less inefficient than an iterator?
You can hide "control variable" in an upvalue:
local function selpairs(ary, sel)
local s = 0
return
function()
s = s + 1
local i = sel[s]
local v = ary[i]
if v then
return i, v
end
end
end
Usage:
local ary = {10,20,30,40}
for i, v in selpairs(ary, {1,3}) do
ary[i] = v+5
print(string.format("ary[%d] is now = %g", i, ary[i]))
end
Nested usage:
local ary_of_arys = {
{10, 20, 30, 40},
{5, 6, 7, 8},
{0.9, 1, 1.1, 1.2},
}
local outer_indices = {1,3}
local inner_indices = {2,3,4}
for aoa, ary in selpairs(ary_of_arys, outer_indices) do
for i, v in selpairs(ary, inner_indices) do
ary[i] = v+5 -- This is the same as ary_of_arys[aoa][i] = v+5
end
end
Not sure if I understand what you want to achive but why not simply write
local values = {"a", "b", "c", "d"}
for i,key in ipairs {3,4,1} do
print(values[key])
end
and so forth, instead of implementing all that interator stuff? I mean your use case is rather simple. It can be easily extended to more dimensions.
And here's a co-routine based possibility:
function selpairs(t,selected)
return coroutine.wrap(function()
for _,k in ipairs(selected) do
coroutine.yield(k,t[k])
end
end)
end

Length of nested array lua

I am having trouble figuring out how to get the length of a matrix within a matrix within a matrix (nested depth of 3). So what the code is doing in short is... looks to see if the publisher is already in the array, then it either adds a new column in the array with a new publisher and the corresponding system, or adds the new system to the existing array publisher
output[k][1] is the publisher array
output[k][2][l] is the system
where the first [] is the amount of different publishers
and the second [] is the amount of different systems within the same publisher
So how would I find out what the length of the third deep array is?
function reviewPubCount()
local output = {}
local k = 0
for i = 1, #keys do
if string.find(tostring(keys[i]), '_') then
key = Split(tostring(keys[i]), '_')
for j = 1, #reviewer_code do
if key[1] == reviewer_code[j] and key[1] ~= '' then
k = k + 1
output[k] = {}
-- output[k] = reviewer_code[j]
for l = 1, k do
if output[l][1] == reviewer_code[j] then
ltable = output[l][2]
temp = table.getn(ltable)
output[l][2][temp+1] = key[2]
else
output[k][1] = reviewer_code[j]
output[k][2][1] = key[2]
end
end
end
end
end
end
return output
end
The code has been fixed here for future reference: http://codepad.org/3di3BOD2#output
You should be able to replace table.getn(t) with #t (it's deprecated in Lua 5.1 and removed in Lua 5.2); instead of this:
ltable = output[l][2]
temp = table.getn(ltable)
output[l][2][temp+1] = key[2]
try this:
output[l][2][#output[l][2]+1] = key[2]
or this:
table.insert(output[l][2], key[2])

call values that have a common key in Lua

1Is there a way to write a function to multiply two values based on only the fact that they have the same key? Here is some psudocode for what I have in mind:
operation = {a=12, b=7, c=31}
operator1 = {a=0.5}
operator2 = {a=0.7}
operator3 = {b=0.3}
function Operate(x)
return x.common_key * operation.common_key
end
print (Operate (operator1))
print (Operate (operator3))
---> 6
---> 2.1
This code of course doesn't work, because "common_key" isn't a real thing. It is a stand-in for whatever the function's argument has in common with the "operation" dictionary. In this case, it would be "a", so the function would multiply "operator1.a" and "operation.a" if it could.
You can use the pairs function to iterate over a table, allowing you to inspect what keys it has available. Additionally, you can access tables with t[k] notation instead of t.name if k is the "name" string and lua tables return nil if you access a key that it doesn't have.
function find_common_keys(t1, t2)
for k,v1 in pairs(t1) do
local v2 = t2[k]
if v2 ~= nil then
print("Found match", k, v1, v2)
end
end
end

Lua Table Comparisons Within Tables

So I have a table that holds references to other tables like:
local a = newObject()
a.collection = {}
for i = 1, 100 do
local b = newObject()
a[#a + 1] = b
end
Now if I want to see if a particular object is within "a" I have to use pairs like so:
local z = a.collection[ 99 ]
for i,j in pairs( a.collection ) do
if j == z then
return true
end
end
The z object is in the 99th spot and I would have to wait for pairs to iterate all the way throughout the other 98 objects. This set up is making my program crawl. Is there a way to make some sort of key that isn't a string or a table to table comparison that is a one liner? Like:
if a.collection[{z}] then return true end
Thanks in advance!
Why are you storing the object in the value slot and not the key slot of the table?
local a = newObject()
a.collection = {}
for i = 1, 100 do
local b = newObject()
a.collection[b] = i
end
to see if a particular object is within "a"
return a.collection[b]
If you need integer indexed access to the collection, store it both ways:
local a = newObject()
a.collection = {}
for i = 1, 100 do
local b = newObject()
a.collection[i] = b
a.collection[b] = i
end
Finding:
local z = a.collection[99]
if a.collection[z] then return true end
Don't know if it's faster or not, but maybe this helps:
Filling:
local a = {}
a.collection = {}
for i = 1, 100 do
local b = {}
a.collection[b] = true -- Table / Object as index
end
Finding:
local z = a.collection[99]
if a.collection[z] then return true end
If that's not what you wanted to do you can break your whole array into smaller buckets and use a hash to keep track which object belongs to which bucket.
you might want to consider switching from using pairs() to using a regular for loop and indexing the table, pairs() seems to be slower on larger collections of tables.
for i=1, #a.collection do
if a.collection[i] == z then
return true
end
end
i compared the speed of iterating through a collection of 1 million tables using both pairs() and table indexing, and the indexing was a little bit faster every time. try it yourself using os.clock() to profile your code.
i can't really think of a faster way of your solution other than using some kind of hashing function to set unique indexes into the a.collection table. however, doing this would make getting a specific table out a non-trivial task (you wouldn't just be able to do a.collection[99], you'd have to iterate through until you found one you wanted. but then you could easily test if the table was in a.collection by doing something like a.collection[hashFunc(z)] ~= nil...)

Resources