818 posts
Posted 07 January 2015 - 06:05 PM
So I have a door control system with a filesystem like structure where different doors are adressed by an adress which coresponds to a table. I've got almost everything done except for being able to move up 1 level in the system, similar to typing ".." in a file system
What I want to do now is being able to from an adress remove 1 step when backspace is pressed, for example making "all.Doors.AE2" into "all.Doors". I know how os.pullEvent and all that stuff works, but the specific function to use to remove everything including and after the first period from the end is where im lost. Barely used any of the string functions before.
If full code is needed
http://pastebin.com/sEE5XhXz
Edited on 07 January 2015 - 05:12 PM
3057 posts
Location
United States of America
Posted 07 January 2015 - 06:31 PM
String.match and string.reverse are helpful here. String.reverse() inverts the string, so now we need to remove the front part of the string. Next, we can use string.match to extract only what we want from the string. Then, we reverse what is left.
function removeLastDecimal( str )
return str:reverse():match( ".-%.(.+)" ):reverse()
end
The pattern I used here ".-%.(.+)" can be broken into three peices
1 ".-" this takes everything until encountering something matching the next part of the pattern
2 "%." since . is a "magic" character, I escape it with '%' to match a period/decimal.
3 "(.+)" the parentheses cause the match() function to return what is inside of them, which is everything left in the string.
If you have any questions, feel free to ask.
1140 posts
Location
Kaunas, Lithuania
Posted 07 January 2015 - 06:37 PM
No need for reverse here:
local str = ("test.string.three"):match("(.+)%..-")
3057 posts
Location
United States of America
Posted 07 January 2015 - 06:39 PM
No need for reverse here:
local str = ("test.string.three"):match("(.+)%..-")
That's assuming he always has two decimals. I don't think he does.
818 posts
Posted 07 January 2015 - 06:47 PM
Didn't quite think of this, but how do I convert that string into an adress, making "all.Doors" into all.Doors? Is loadstring() the appropriate function?
1140 posts
Location
Kaunas, Lithuania
Posted 07 January 2015 - 07:05 PM
No need for reverse here:
local str = ("test.string.three"):match("(.+)%..-")
That's assuming he always has two decimals. I don't think he does.
Actually it does exactly the same as your code and both of our codes have one problem: they will return nil if there is not a single dot in that string. Here's a 'fixed' and simplified version of our both codes:
local function removeLastDecimal ( str )
return str:match( "(.*)%..-" ) or ""
end
Didn't quite think of this, but how do I convert that string into an adress, making "all.Doors" into all.Doors? Is loadstring() the appropriate function?
If you are using a table then you can index it like this:
local levels = {
one = {
two = 1
}
}
print( levels["one"]["two"] ) --> 1
If you want to get the index from a string like 'one.two' then you would have to parse that string. Something like this should work:
local function getIndex (tab, str)
local t = tab --# a variable to store the last element we could get from the table
for key in str:gmatch("[^%.]+") do --# iterate through every word in a string that doesn't contain a dot in it
if not t[key] then break end --# if the key is nil or false break from the loop
t = t[key] --# get the next value of the table
end
return t --# return the last value we got from the table
end
local levels = {
one = {
two = 1
}
}
print( getIndex(levels, "one.two") )
If you have questions about any part of the code feel free to ask :)/>, it's important that you understand what the code does rather than just blindly copy-paste it.
Edited on 07 January 2015 - 06:07 PM
227 posts
Location
Germany
Posted 07 January 2015 - 07:53 PM
Um, all this string reversing and confusion 'n stuff. How about just using
local function removePart( str )
return str:match( "^(.+)%." ) or str
end
?
This will also return the same string if there is no lower level available.
For using that string with a table MKlego, I think, pretty much has the solution.
376 posts
Location
[string "FindMe"]:23143: bad argument #1 to 'returnPos' (vector expected, got nil)
Posted 07 January 2015 - 07:54 PM
just use string.sub …
EDIT : Forget what I said, my code was very clunky compared to all the others.
Edited on 07 January 2015 - 06:56 PM
818 posts
Posted 07 January 2015 - 08:14 PM
Got it to work, thanks everyone!
Final code for reference and for lazy people from the future
t = all
sCurFolder = sCurFolder:match( "(.*)%..-" ) or ""
for key in sCurFolder:gmatch("[^%.]+") do
if not t[key] then break end
t = t[key]
end
curFolder = t