table.find
Forum rules
This is a sub-forum for things specific to MicroMacro.
This is not the place to ask questions about the RoM bot, which uses MicroMacro. There is a difference.
This is a sub-forum for things specific to MicroMacro.
This is not the place to ask questions about the RoM bot, which uses MicroMacro. There is a difference.
table.find
I think the lack of a function for table.find is kind of annoying, what do you think about adding a function into MM for this??
Not sure how many times I think, yeah that would make life so much easier lol
It would no doubt need to be rather complex to allow for all situations in a table (lots of checks) but it should be easy enough to do.
I am thinking
return true/false, number of occurances, place/s in table it occurs
so bool, numeral, table
Any thoughts?
Not sure how many times I think, yeah that would make life so much easier lol
It would no doubt need to be rather complex to allow for all situations in a table (lots of checks) but it should be easy enough to do.
I am thinking
return true/false, number of occurances, place/s in table it occurs
so bool, numeral, table
Any thoughts?
Remember no matter you do in life to always have a little fun while you are at it 
wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual
Re: table.find
This might be a little messy but just to give you an idea, it does it all in strings and no number searches, so converts numbers to strings.
I deliberately made it so it only counted 1 if it was a table in a table.
Example
{1,{2,3},2,7,{3,{1,8,6,2},8,2},4,5}
5th spot in the table has 2 lots of 2
{3,{1,8,6,2},8,2}
but it will only count it once, not sure if that is ideal or not.
Code: Select all
function table.find(_table,_string)
if type(_table) ~= "table" then return "Argument 1 must be a table" end
if type(_string) == "number" then _string = tostring(_string) end
if type(_string) ~= "string" then return "Incorrect usage of Argument 2" end
local count = 0
local found = {}
local function _digdeep(_arg1,_arg2)
if type(_arg1) == "table" then
for c,d in pairs(_arg1) do
if type(d) == "table" then
if _digdeep(d,_arg2) then
return true
end
else
if string.find(d,_string) then
return true
end
end
end
else
_arg1 = tostring(_arg1)
if string.find(_arg1,_string) then
return true
end
end
end
for k,v in ipairs(_table) do
if type(v) ~= "table" then
v = tostring(v)
if string.find(v,_string) then
count = count + 1
table.insert(found,k)
end
else
if _digdeep(v,_string) then
count = count + 1
table.insert(found,k)
end
end
end
if count ~= 0 then
return true, count, found
else
return false, count
end
end
Code: Select all
Command> local tt = {1,{2,3},2,3,4,5} aa,bb,cc = table.find(tt,2) if aa then table.print(cc) end
table: 01A405E8
1: 2
2: 3
Command> local tt = {1,{2,3},2,3,4,5} print(table.find(tt,2))
true 2 table: 01A40390
Command> local tt = {1,{2,3},2,7,{3,2},4,5} aa,bb,cc = table.find(tt,2) if aa then table.print(cc) end
table: 01A40890
1: 2
2: 3
3: 5
Command> local tt = {1,{2,3},2,7,{3,{1,8,6,2},8,2},4,5} aa,bb,cc = table.find(tt,2) if aa then table.print(cc) end
table: 01A78F60
1: 2
2: 3
3: 5
Example
{1,{2,3},2,7,{3,{1,8,6,2},8,2},4,5}
5th spot in the table has 2 lots of 2
{3,{1,8,6,2},8,2}
but it will only count it once, not sure if that is ideal or not.
Remember no matter you do in life to always have a little fun while you are at it 
wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual
Re: table.find
Ok reason I posted this.
I have this
which is fine if I only want to use 1 type but if I wanted to use more than 1 type then it would be more complex.
But with the table.find I could do
I have this
Code: Select all
--NTYPE_WOOD = 1
--NTYPE_ORE = 2
--NTYPE_HERB = 3
_node = 1
if database.nodes[obj.Id] and database.nodes[obj.Id].Type == _node then
Code: Select all
--NTYPE_WOOD = 1
--NTYPE_ORE = 2
--NTYPE_HERB = 3
_node = {1,3}
if database.nodes[obj.Id] then
for k,v in pairs(_node) do
if v == database.nodes[obj.Id].Type then
Code: Select all
--NTYPE_WOOD = 1
--NTYPE_ORE = 2
--NTYPE_HERB = 3
_node = {1,3}
if database.nodes[obj.Id] and table.find(_node,database.nodes[obj.Id].Type) then
Remember no matter you do in life to always have a little fun while you are at it 
wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual
Re: table.find
For starters, you only search indexed tables?
I'm not really sure how useful searching sub elements is going to be. I think most uses will be searching for 1 level table. Or, at most, looking for a particular sub-element of a table.
Example:
Or
Eg.
I'm not really sure how useful searching sub elements is going to be. I think most uses will be searching for 1 level table. Or, at most, looking for a particular sub-element of a table.
Example:
- tt= {val1=1,val2=3,val3=7}
Or
- tt={
- {name="lisa",X=123,Z=234,Y=34},
{name="rock5",X=123,Z=234,Y=34},
} - {name="lisa",X=123,Z=234,Y=34},
Eg.
- table.find(tt,function(a) return a == 7 end)
- table.find(tt,function(a) return a.name == "lisa" end)
- Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
- I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
- How to: copy and paste in micromacro
________________________
Quote:- “They say hard work never hurt anybody, but I figure, why take the chance.”
- Ronald Reagan
- Administrator
- Site Admin
- Posts: 5329
- Joined: Sat Jan 05, 2008 4:21 pm
Re: table.find
I'm not opposed to adding something like this. There is already a function, table.contains(), which returns true/false if a table contains a specific value. I think it should, at least, return the index of the found match, so I've added that.
Now, you also want a function that returns the number of occurrences. Could also be useful, I suppose. I think it would be important to separate these two (if not different functions then a switch to enable it, default to disabled) due to 99% of the time it being just a waste since you'll normally only want to know if the table contains a value.
Now, you also want a function that returns the number of occurrences. Could also be useful, I suppose. I think it would be important to separate these two (if not different functions then a switch to enable it, default to disabled) due to 99% of the time it being just a waste since you'll normally only want to know if the table contains a value.
Re: table.find
I didn't know about table.contains()
If nothing else I sparked up a conversation about it =)
If nothing else I sparked up a conversation about it =)
Remember no matter you do in life to always have a little fun while you are at it 
wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual
- Administrator
- Site Admin
- Posts: 5329
- Joined: Sat Jan 05, 2008 4:21 pm
Re: table.find
Indeed. I think I'm going to have to side against nested searching. If it were needed, a recursion function could be written up quickly to take care of it. The problem here is that it is slow and complex (relatively) by nature and would be awkward to make flexible enough to fit all cases in one function.
Re: table.find
Here's my take on it.
For the second argument it accepts strings or numbers to do a regular 1 level search, or an eval function. The function should accept key and value and return true or false. The function returns a table of indexes.
Example of a regular search.
Example of an evalfunc search for NPC locations.
Now that I included the key value in the evalfunc you can also search for keys. This example lists all the player values that include 'hp' in it.
So what do you think of my take?
Code: Select all
function table.find (_table, _strOrFunc)
local str,func
if type(_table) ~= "table" then print("Argument 1 must be a table") end
if type(_strOrFunc) == "number" or type(_strOrFunc) == "string" then
str = _strOrFunc
elseif type(_strOrFunc) == "function" then
func = _strOrFunc
else
print("Incorrect usage of Argument 2", type(_strOrFunc))
end
found = {}
for k,v in pairs(_table) do
if str then
if string.find(v,str) then
table.insert(found,k)
end
else -- must be func
if func(k,v) then
table.insert(found,k)
end
end
end
return found
end
Example of a regular search.
Code: Select all
Command> names={"lisa","roc","rock5","bill d cat"} f=table.find(names,"roc")
Command> print("Count",#f) table.print(f)
Count 2
table: 05754BE8
1: 2
2: 3
Code: Select all
Command> ol=CObjectList() ol:update() f=table.find(ol.Objects,function(k,v) retu
rn v.Name=="Cadoon Guard" end)
Command> for k,v in pairs(f) do p=ol.Objects[v] printf("Name: %s, XZY: %d, %d, %
d\n",p.Name,p.X,p.Z,p.Y) end
Name: Cadoon Guard, XZY: 3914, -7931, 447
Name: Cadoon Guard, XZY: 3816, -7916, 448
Name: Cadoon Guard, XZY: 3850, -7908, 444
Name: Cadoon Guard, XZY: 3852, -7913, 444
Code: Select all
Command> hp=table.find(player,function(k,v) return string.find(string.lower(k),"
hp") end) table.print(hp)
table: 05755EF8
1: PotionLastHpEmptyTime
2: HP
3: PhiriusHpUsed
4: PotionHpUsed
5: PhiriusLastHpEmptyTime
6: PotionLastHpOnceEmptyTime
7: PotionHpOnceUsed
8: MaxHP
- Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
- I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
- How to: copy and paste in micromacro
________________________
Quote:- “They say hard work never hurt anybody, but I figure, why take the chance.”
- Ronald Reagan
Re: table.find
looks better than my version and I can also see that it has more uses aswell than my version.
I wonder how the speed would compare to previous ways of doing things.
I wonder how the speed would compare to previous ways of doing things.
Remember no matter you do in life to always have a little fun while you are at it 
wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual
Re: table.find
I did a bit of testing.
My find
Custom function
Hm.. 2.5 times longer. It's because of the 'if's in the loop.
This should be better.That's better and I think quite acceptable considering they are both under a ms.
And I just tested the overhead of the function, that's everything except the actual search, took 0.02ms which means the actual search difference is more like 0.1ms to 0.14ms. So 40%.
My find
Code: Select all
Command> ol=CObjectList() ol:update() local st=getTime() f=table.find(ol.Objects
,function(k,v) return string.match(v.Name,"Foundation") end) st=deltaTime(getTim
e(),st) print("time took",st)
time took 0.2405154949447
Code: Select all
Command> ol=CObjectList() ol:update() local st=getTime() f={} for k,v in pairs(o
l.Objects) do if string.match(v.Name,"Foundation") then table.insert(f,k) end en
d st=deltaTime(getTime(),st) print("time took",st)
time took 0.10131449167582
This should be better.
Code: Select all
function table.find (_table, _strOrFunc)
local str,func
if type(_table) ~= "table" then print("Argument 1 must be a table") end
if type(_strOrFunc) == "number" or type(_strOrFunc) == "string" then
str = _strOrFunc
elseif type(_strOrFunc) == "function" then
func = _strOrFunc
else
print("Incorrect usage of Argument 2", type(_strOrFunc))
end
found = {}
if str then
for k,v in pairs(_table) do
if string.find(v,str) then
table.insert(found,k)
end
end
else -- must be func
for k,v in pairs(_table) do
if func(k,v) then
table.insert(found,k)
end
end
end
return found
end
Code: Select all
Command> ol=CObjectList() ol:update() local st=getTime() f=table.find(ol.Objects
,function(k,v) return string.match(v.Name,"Foundation") end) st=deltaTime(getTim
e(),st) print("time took",st)
time took 0.16176263376812
And I just tested the overhead of the function, that's everything except the actual search, took 0.02ms which means the actual search difference is more like 0.1ms to 0.14ms. So 40%.
- Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
- I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
- How to: copy and paste in micromacro
________________________
Quote:- “They say hard work never hurt anybody, but I figure, why take the chance.”
- Ronald Reagan
- Administrator
- Site Admin
- Posts: 5329
- Joined: Sat Jan 05, 2008 4:21 pm
Re: table.find
Looks good to me. Now, the only thing is with the string search, do you want to default to allowing substrings (ie. "roc" matching in "rock5" per your example), or should it only allow full matches? What about regular expressions?
Allowing the regular expressions makes it more powerful, but then opens up the possibility of people overlooking that and using pattern characters which could give them some strange results. I'm not against it, just need to consider it.
Allowing the regular expressions makes it more powerful, but then opens up the possibility of people overlooking that and using pattern characters which could give them some strange results. I'm not against it, just need to consider it.
Re: table.find
Initially I would have just done exact matches but I used the substring search because Lisa did. If we include substring searches I think it would be better without regex to make it more reliable to regular users who don't know about pattern characters. If we need to use regex we could always use the eval function.
I used this function recently and realized that it might not be as useful as it first seems. The idea of this function is to replace the for loop, looping through a table, with a function call. But after you get your results you have to create a for loop anyway to iterate through the results. If all you did with a for loop was search for something then the function will save time but usually, in many cases, a needed action is performed on the found item inside the for loop. In that case the function could actually make the code longer
Lets see if I can make up an example.
Old way
New way
My example ended up having 2 for loops which made it interesting. And I came up with a solution that didn't need to iterate through the results because I deleted the items in the eval function. That ended up taking fewer lines. Technically it would take longer because it doesn't break when it finds a result in the DiscardList.
Maybe we should include an option to return the first match if the user expects only one match or only needs the first match. Maybe
I used this function recently and realized that it might not be as useful as it first seems. The idea of this function is to replace the for loop, looping through a table, with a function call. But after you get your results you have to create a for loop anyway to iterate through the results. If all you did with a for loop was search for something then the function will save time but usually, in many cases, a needed action is performed on the found item inside the for loop. In that case the function could actually make the code longer

Old way
Code: Select all
for _, item in pairs(inventory.BagSlot) do
for _, toss in pairs(DiscardList) do
if string.find(item,toss) then
item:delete()
break
end
end
end
Code: Select all
function eval(k,v)
if table.find(DiscardList,v.Name) then
v:delete
end
end
items = table.find(inventory.BagSlot,eval)
Maybe we should include an option to return the first match if the user expects only one match or only needs the first match. Maybe
- table.find(_table,_val,_firstmatchonly)
- Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
- I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
- How to: copy and paste in micromacro
________________________
Quote:- “They say hard work never hurt anybody, but I figure, why take the chance.”
- Ronald Reagan
Who is online
Users browsing this forum: No registered users and 0 guests