gmod_game: Better/shorter string.Explode suggested by TomyLob..
4 replies, posted
[B]Revision 875[/B]
[INDENT]Better/shorter string.Explode suggested by TomyLobo[/INDENT] [B]Changed Files:[/B]
[LIST]
[*][URL="https://facepunch.svn.beanstalkapp.com/gmodgame/trunk/lua/includes/extensions/string.lua"]trunk/lua/includes/extensions/string.lua[/URL]
[/LIST]
Committed By [B]Alexander Overvoorde[/B]
You committed the wrong one, without the modifications I sent you later.
Also, in the meantime, Divran found out that this version sucks for long strings so I wrote another one that performs much better for long strings but worse for short ones and he combined the two into this:
--snip--
divran did some more benchmarks, he'll post an optimized version of of that 2nd version in a minute
Just in case Divran's pastebin disappears, here's a gist mirror:
[url]https://gist.github.com/TomyLobo/a51be4b0b95c3db9bfdcefae35b62e24[/url]
Here are some test results.
"Explode1" is one with both of the two explode functions described below, with a string length check (see the code above).
"Explode2" is the one with only the "()" .. sep .. "()" pattern.
"Explode3" is the one with the "(.-)" .. sep .. "()" pattern.
Test results: [url]http://pastebin.com/6wQP9MSq[/url]
This means that #3 (the one with the "(.-) .. ()" pattern) is faster than #2 (the one with "() .. ()") when the parts in between the separators are very short. The length of the string does not matter.
The time #3 takes to finish depend on the length of the parts. When they get bigger, the function gets slower.
#2 does not suffer from this at all and runs at a constant speed pretty much all the time. It runs slightly slower when there are multiple separators in the string, but that's barely noticeable.
I'd go with #2.
EDIT:
I just tried localizing string.sub at the top, and that made #2 another 0.01 seconds faster when running the third test.
And by the way, here's the final code:
[lua]local totable = string.ToTable
local string_sub = string.sub
local string_gsub = string.gsub
local string_gmatch = string.gmatch
function string.Explode(separator, str, withpattern)
if (separator == "") then return totable( str ) end
local ret = {}
local index,lastPosition = 1,1
-- Escape all magic characters in separator
if not withpattern then separator = string_gsub( separator, "[%-%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%1" ) end
-- Find the parts
for startPosition,endPosition in string_gmatch( str, "()" .. separator.."()" ) do
ret[index] = string_sub( str, lastPosition, startPosition-1)
index = index + 1
-- Keep track of the position
lastPosition = endPosition
end
-- Add last part by using the position we stored
ret[index] = string_sub( str, lastPosition)
return ret
end[/lua]
Alright, but this is the last time I'm going to change it.
Please use this for string.Replace, your one doesn't stop the pattern patching properly.
[lua]
local MAGIC_CHARACTERS = "([%(%)%.%%%+%-%*%?%[%^%$])";
function string.Replace(text, find, replace)
return ( text:gsub(find:gsub(MAGIC_CHARACTERS, "%%%1"), replace) );
end;
[/lua]
Sorry, you need to Log In to post a reply to this thread.