Jump to content




Splitting String With \n Into Table of Strings


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

#1 augustas656

  • Members
  • 158 posts

Posted 23 May 2014 - 09:41 PM

How could create perhaps like a for loop, or any type of code in a function that takes in a string and finds \n, removes them and splits all the strings in-between, so a string such as 123\nabc\n456 would be split into a table of {123, abc, 456}. I know how I could head with this, using string.match, string.sub, or perhaps something like this but I'm still somewhat not sure.

I need this for my API function that firstly if a parameters allows splitting at \n spots, it will split then split the string whrereit finds \n, and after that, it splits the string to the given area, if no area is given it will use screen's width as default. So a string 105 characters would be split into 51, 51 and 3 characters.

Regards
Augustas

#2 Lignum

  • Members
  • 558 posts

Posted 23 May 2014 - 09:49 PM

You'd do something like this:
local lines = {}
local text = "Hello\nWorld!"

--# [^\r?\n\r?] means "anything that isn't a new line, optionally prefixed or suffixed with a carriage return"
for match in text:gmatch("[^\\r?\\n\\r?]") do
	 lines[#lines + 1] = match
end


See theoriginalbit's answer.

Edited by Lignum, 24 May 2014 - 08:23 AM.


#3 augustas656

  • Members
  • 158 posts

Posted 23 May 2014 - 10:01 PM

Can you please explain what do yuo mean by optionally prefixed or suffixed with a carriage return?

Regards
Augustas

I'm sorry, your code splits my string into char after char, so like hello world is split into h, e, l, l, o, , w, o, r, l, d?

Edited by augustas656, 23 May 2014 - 09:58 PM.


#4 CometWolf

  • Members
  • 1,283 posts

Posted 23 May 2014 - 10:07 PM

He forgot to add a + sign to his custom character class
text:gmatch("[^\\r?\\n\\r?]+")
Although i can't say wether it will work or not still, since i believe +-? and the like don't work the same way within custom classes. Something like
text:gmatch("(.+)\n?")
would probably be enough

Personally i use string.find for this, so idk, it mgiht work, it might not. Give it a try i suppose.

Edited by CometWolf, 23 May 2014 - 10:08 PM.


#5 augustas656

  • Members
  • 158 posts

Posted 23 May 2014 - 10:19 PM

How do you (personally CometWolf) use string.find? I personally done something while there's an \n array[#array + 1] is equal to the string before \n, then string is string removed the first part including the \n. But the problem with that is it doesn't include the last remaining part of the string after the last \n.

Regards
Augustas

#6 augustas656

  • Members
  • 158 posts

Posted 23 May 2014 - 10:27 PM

Okay I got it to work with the +, thanks, but can someone explain what Lignum meant by optionally prefixed or suffixed with a carriage return?

Regards
Augustas

#7 CometWolf

  • Members
  • 1,283 posts

Posted 23 May 2014 - 10:41 PM

"\r" is the character for carriage return, and the question mark means they are an optional match, ie. not needed. However i don't believe question marks work that way within custom classes([]).
For the record, here's the function i use
string.lineFormat = function(text,lineLength,center)
  local tLines = {}
  while #text > 0 do  --splits text into a table containing each line
    local line = text:sub(1,lineLength)
    local newLine = string.find(line.."","\n") --check for new line character
    if newLine then
	  line = line:sub(1,newLine-1)
	  text = text:sub(#line+2,#text)
    elseif #line == lineLength then
	  local endSpace = line:find"%s$" or line:find"%s%S-$" or lineLength
	  line = line:sub(1,endSpace)
	  text = text:sub(#line+1)
    else
	  text = ""
    end
    if center then
	  line = string.rep(" ",math.max(math.floor((lineLength-#line)/2),0))..line
	  line = line..string.rep(" ",math.max(lineLength-#line,0))
    end
    tLines[#tLines+1] = line
  end
  return tLines
end


#8 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 24 May 2014 - 12:23 AM

View PostLignum, on 23 May 2014 - 09:49 PM, said:

You'd do something like this:
local lines = {}
local text = "Hello\nWorld!"

--# [^\r?\n\r?] means "anything that isn't a new line, optionally prefixed or suffixed with a carriage return"
for match in text:gmatch("[^\\r?\\n\\r?]") do
	 lines[#lines + 1] = match
end
did you actually test your code before posting it to 'help'? I have a feeling you didn't!

adding a table.concat(lines, ' ') at the end of your script will show you why I think this... here's the output
H e l l o
 W o r l d !
notice how the new line is still there, that is because you've escaped the backslash by doing \\ ... newline is \n or \r and the combinations of those two, so your loop should look like
for match in text:gmatch("[^\r?\n\r?]") do
  lines[#lines + 1] = match
end
however that still 'causes one little problem, take a look at the output from the table.concat
H e l l o W o r l d !
now this output is because your pattern has it ignore new lines, however it only does that one character... CometWolf's response holds the answer, your loop should look like this
for match in text:gmatch("[^\r?\n\r?]+") do
  lines[#lines + 1] = match
end
now if you take a look at the output from table.concat you'll notice it has worked as intended
Hello World!


I don't like having to correct the 'pros' but sadly its getting to the point where 1) people either don't know what they're talking about when trying to help, or 2) they don't test their code before posting, a crucial step in making sure you provide accurate help, not just more problems and headaches for the OP.

Edited by theoriginalbit, 24 May 2014 - 12:23 AM.


#9 Lignum

  • Members
  • 558 posts

Posted 24 May 2014 - 08:23 AM

View Posttheoriginalbit, on 24 May 2014 - 12:23 AM, said:

did you actually test your code before posting it to 'help'? I have a feeling you didn't!
No, I didn't. This seemed simple enough to me but it was a little late at night... a bit very late.
Anyway, sorry about that. Confidence is evil.





2 user(s) are reading this topic

0 members, 2 guests, 0 anonymous users