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

[Lua][Help]Separating parts of a string.

Started by ChaddJackson12, 22 November 2012 - 05:55 PM
ChaddJackson12 #1
Posted 22 November 2012 - 06:55 PM
Is it possible to separate a string, and if so, could it be done with custom 'separators'? If so I would use this for rednet or something. An example would be something like this:

rednet.send(1, "Stuff, more stuff, even more stuff")
rather than doing something like this:

rednet.send(1, "Stuff")
rednet.send(1, "more stuff")
rednet.send(1, "even more stuff")
Is there a string command or something that separates them? Like when doing parameters or arguments? Also, if there is a way to do that, is there a way use custom separators? Like, instead of a comma, a period. Please help me out, thanks in advance.
Lyqyd #2
Posted 22 November 2012 - 06:56 PM
You can use string.match or string.gmatch, as your situation warrants.
ChaddJackson12 #3
Posted 22 November 2012 - 07:00 PM
You can use string.match or string.gmatch, as your situation warrants.
Can you please give an example on how this would be done On the receiving end of the computer? Because I am not very smart with this kind of stuff ;)/>/>
Kingdaro #4
Posted 22 November 2012 - 07:02 PM
I think using a split function would help you more here. There are some implementations on lua-users, and I'm pretty sure some people have created some string utilities around these forums.

Copied from lua-users:

function split(str, pat)
   local t = {}
   local fpat = "(.-)" .. pat
   local last_end = 1
   local s, e, cap = str:find(fpat, 1)
   while s do
      if s ~= 1 or cap ~= "" then
	 table.insert(t,cap)
      end
      last_end = e+1
      s, e, cap = str:find(fpat, last_end)
   end
   if last_end <= #str then
      cap = str:sub(last_end)
      table.insert(t, cap)
   end
   return t
end

You could just split your string, then go through the table it returns and then rednet.send() the strings individually.

-- your split() implementation here

local str = 'Stuff, more stuff, even more stuff'
local splitTable = split(str)

for i=1, #splitTable do
  rednet.send(1, splitTable[i])
end
ChaddJackson12 #5
Posted 22 November 2012 - 07:06 PM
I think using a split function would help you more here. There are some implementations on lua-users, and I'm pretty sure some people have created some string utilities around these forums.

Copied from lua-users:

function split(str, pat)
   local t = {}
   local fpat = "(.-)" .. pat
   local last_end = 1
   local s, e, cap = str:find(fpat, 1)
   while s do
	  if s ~= 1 or cap ~= "" then
	 table.insert(t,cap)
	  end
	  last_end = e+1
	  s, e, cap = str:find(fpat, last_end)
   end
   if last_end <= #str then
	  cap = str:sub(last_end)
	  table.insert(t, cap)
   end
   return t
end

You could just split your string, then go through the table it returns and then rednet.send() the strings individually.

-- your split() implementation here

local str = 'Stuff, more stuff, even more stuff'
local splitTable = split(str)

for i=1, #splitTable do
  rednet.send(1, splitTable[i])
end

Well, in that case, could you separate what is received? Instead of what is being sent?
Kingdaro #6
Posted 22 November 2012 - 07:07 PM
Yes. In my script, "str" would be whatever string received.
Lyqyd #7
Posted 22 November 2012 - 07:09 PM
I wouldn't trust that split() function necessarily. LuaJ has some weird issues with string.find and string.sub interacting.

You could just:


id, message = rednet.receive()
firstPart, secondPart = string.match(message, "(%w+),(%w+)")
Kingdaro #8
Posted 22 November 2012 - 07:11 PM
That doesn't really work well when you have more than just two elements, or however many one decides to define.

Besides, there are plenty more implementations that use different methods that aren't as "dangerous".
ChaddJackson12 #9
Posted 22 November 2012 - 07:12 PM
I wouldn't trust that split() function necessarily. LuaJ has some weird issues with string.find and string.sub interacting.

You could just:


id, message = rednet.receive()
firstPart, secondPart = string.match(message, "(%w+),(%w+)")
Ok, another question… What is the the part in string.match that is in quotes? "(%w+)", What does it mean? Also, how could I use the information after it is used in string.match?
Lyqyd #10
Posted 22 November 2012 - 07:18 PM
Check out the documentation on string.match (and string.gmatch while you're at it!). The patterns are explained a little ways below, but basically what that says is that:

(%w+)
( - start a capture
%w - match all letters and numbers
+ - match one or more (of all letters and numbers, since it followed %w)
) - end the capture.

So, that would match each of the following strings:

apple
a1b2c3po
banana
CrApApPlEcAkEs

More advanced uses of patterns open up many opportunities.

That doesn't really work well when you have more than just two elements, or however many one decides to define.

Besides, there are plenty more implementations that use different methods that aren't as "dangerous".

If you aren't parsing a known-element-count string, you use string.gmatch and put the results into a table, which is more efficient than the split() function anyway.
Kingdaro #11
Posted 22 November 2012 - 07:28 PM
If you aren't parsing a known-element-count string, you use string.gmatch and put the results into a table, which is more efficient than the split() function anyway.
gmatch alone doesn't necessarily help very well when the string is formatted with "something, something, something". Splitting functions were made with accounting for the missing delimiter at the end. The one I posted isn't the most efficient function, but as I've said, there are better implementations out there.
Lyqyd #12
Posted 22 November 2012 - 07:39 PM
string.gmatch(str, "([^,]+)") should match each of the three just fine. Honestly, the split() function seems to just be a long way to do a single-inverse-character gmatch, except that it also dumps it into a table at the same time.
Watcher7 #13
Posted 22 November 2012 - 07:40 PM
If you aren't parsing a known-element-count string, you use string.gmatch and put the results into a table, which is more efficient than the split() function anyway.
gmatch alone doesn't necessarily help very well when the string is formatted with "something, something, something". Splitting functions were made with accounting for the missing delimiter at the end. The one I posted isn't the most efficient function, but as I've said, there are better implementations out there.
If you're saying string.gmatch() won't be able to handle a missing comma (or any other delimiter) at the end you are wrong.
http://codepad.org/bThNappI

EDIT:
M'kay the lack of new post notifications is annoying me even more now.
I don't like repeating what someone has posted 1 minute before I posted.