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

string split function

Started by Sewbacca, 04 April 2016 - 05:36 PM
Sewbacca #1
Posted 04 April 2016 - 07:36 PM
I found this function to split strings:


local split = function(inputstr, sep)
  if sep == nil then
	sep = "%s"
  end
  sep = tostring(sep)
  local t={} ; i=1
  for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
	t[i] = str
	i = i + 1
  end
  return t
end

My problem:

split('a\nb\n\nc', '\n') –> {'a','b','c'}

This can be useful, but for my code it isnt.
How can I modify the function to get:

{'a','b','','c'}

Granted, I can't deal with string.gmatch.
Edited on 04 April 2016 - 08:37 PM
valithor #2
Posted 04 April 2016 - 09:32 PM
Your function accepts a argument for a separator. In this case you want to separator to be the new line character "\n" so pass that as your second argument:

split('a\nb\n\nc','\n')

edit:

I didn't see that extra quote in the table that you were wanting, makes the question make more sense.
Edited on 04 April 2016 - 07:34 PM
Dragon53535 #3
Posted 04 April 2016 - 11:30 PM
You'd have to go for a less robust function that utilizes string.find to correctly find the separator character.


local function split(inputString, separatorCharacter)
  if (type(separatorCharacter) ~= "string") then
	separatorCharacter = "\n"
  end
  local returnTable = {}
  local i = 1
  --#We're going to be editing our input string, so we need to know when we're done
  while (inputString ~= "") do
	local start,endNum = string.find(inputString,separatorCharacter)
	if (start == nil) then
	  returnTable[i] = inputString
	  inputString = ""
	else
	  if (start == 1) then
		returnTable[i] = ""
	  else
		returnTable[i] = inputString:sub(1,start-1)
	  end
	  inputString = inputString:sub(endNum+1)
	end
	i = i + 1
  end
  return returnTable
end

Edit: Minor edit to the code so far, i used the variable named end, which is a reserved word and I'm dumb.
Edit2: Lua, why you use ~= and not !=

Edit3: Sigh.. This is being more trouble than I'd love to admit
Edit4: Apparently inputstring:find didn't want to work correctly. It saved the old inputstring as the function.
So it ran once, where inputstring was "a\nb\n\n\c" and then when it ran the second time, even though inputstring changed to "b\n\nc" it thought it was still "a\nb\n\n\c" and gave the location of the 2nd newline
Edited on 04 April 2016 - 09:51 PM
Lyqyd #4
Posted 04 April 2016 - 11:53 PM
Change your gmatch pattern:


"([^"..sep.."]*)"..sep.."?"

This suggestion is untested.
Dragon53535 #5
Posted 05 April 2016 - 01:07 AM
Yep, changing the gmatch pattern to be that works.


local split = function(inputstr, sep)
  if sep == nil then
	    sep = "%s"
  end
  sep = tostring(sep)
  local t={}
  --#I put i down onto it's own line since it wasn't local before
  local i=1
  for str in string.gmatch(inputstr, "([^"..sep.."]*)"..sep.."?") do
	    t[i] = str
	    i = i + 1
  end
  return t
end
Sewbacca #6
Posted 05 April 2016 - 02:40 PM
Thanks