Jump to content




Chopping off part of a string


  • You cannot reply to this topic
8 replies to this topic

#1 Doyle3694

  • Members
  • 815 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 by Doyle3694, 07 January 2015 - 06:12 PM.


#2 KingofGamesYami

  • Members
  • 3,002 posts
  • LocationUnited 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.

#3 MKlegoman357

  • Members
  • 1,170 posts
  • LocationKaunas, Lithuania

Posted 07 January 2015 - 06:37 PM

No need for reverse here:

local str = ("test.string.three"):match("(.+)%..-")


#4 KingofGamesYami

  • Members
  • 3,002 posts
  • LocationUnited States of America

Posted 07 January 2015 - 06:39 PM

View PostMKlegoman357, on 07 January 2015 - 06:37 PM, said:

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.

#5 Doyle3694

  • Members
  • 815 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?

#6 MKlegoman357

  • Members
  • 1,170 posts
  • LocationKaunas, Lithuania

Posted 07 January 2015 - 07:05 PM

View PostKingofGamesYami, on 07 January 2015 - 06:39 PM, said:

View PostMKlegoman357, on 07 January 2015 - 06:37 PM, said:

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

View PostDoyle3694, on 07 January 2015 - 06:47 PM, said:

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 by MKlegoman357, 07 January 2015 - 07:07 PM.


#7 wieselkatze

  • Members
  • 221 posts
  • LocationGermany

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.

#8 Agent Silence

  • Members
  • 319 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 by Requiem of Silence, 07 January 2015 - 07:56 PM.


#9 Doyle3694

  • Members
  • 815 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






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users