This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Doyle3694's profile picture

Chopping off part of a string

Started by Doyle3694, 07 January 2015 - 05:05 PM
Doyle3694 #1
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
KingofGamesYami #2
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.
MKlegoman357 #3
Posted 07 January 2015 - 06:37 PM
No need for reverse here:


local str = ("test.string.three"):match("(.+)%..-")
KingofGamesYami #4
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.
Doyle3694 #5
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?
MKlegoman357 #6
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
wieselkatze #7
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.
Agent Silence #8
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
Doyle3694 #9
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