I noticed that split() splits the table at the first character if you use a separator of more than two characters.
Is it a bug or a specification that split() cannot be used with separators of more than two characters?
foreach(split('123456','45'),print) --123 --56 (Expect only :6) |
Thank you.
Pretty sure separator can only be one character.
There is an alternative: if you pass a number, then the string will be split in groups of this number of characters.
Ah, I =JUST= now ran into this same problem, @shiftalow and @merwok. So yes, I would like it if @zep would allow you to have 2- or more characters recognized in the SPLIT() command.
a="apple::banana" a=split(a,"::") cls() ?a[1] -- correct value ?a[2] -- incorrect value |
Result is APPLE
and a blank line.
I especially wanted it for the following:
function instr(a,b) return #split(a,b)[1]+1 end |
Which works fine when scanning for a single character, however in this case print(instr("coconut","on"))
you get the incorrect answer of 2
truly showing it is looking for just the 1st character.
Oh I've got INSTR() done, @merwok, using SUB() as you said.
-- return from string a where -- string b is first found. function instr(a,b) local r=0 if a>"" and b>"" then for i=1,#a-#b+1 do if sub(a,i,i+#b-1)==b then r=i break end end end return r end |
I was going to put together a bunch of string and numeric functions a bit later, that's one of them.
Ok, I wanted to use it for replace(), but I decided to solve it another way!
> if you pass a number, then the string will be split in groups of this number of characters.
By the way, I use the method of passing a number as an argument, for the purpose of converting hexadecimal numbers into decimal numbers.
function hextodecimal(b,n) a={} foreach(split(b,n or 2),function(v) add(a,tonum('0x'..v)) end) return a end |
Oh, that's great. I found a solution with my replace() using your INSTR as a hint!
Thank you!
function replace(s,f,r) local a,i='',1 while i<=#s do if sub(s,i,i+#f-1)~=f then a..=sub(s,i,i) i+=1 else a..=r or '' i+=#f end end return a end |
Glad to help, @shiftalow. :)
And now that we are at it, here is what I wrote earlier to do a string replace.
-- return replacement of all -- instances in string a of b -- with c. function replace(a,b,c) local r,i=a,1 if a>"" and b>"" and c>"" then r="" repeat if sub(a,i,i+#b-1)==b then r=r..c i=i+#b-1 else r=r..sub(a,i,i) end i=i+1 until i>#a-#b+1 end return r end |
It's always curious and often enlightening to see someone else's solution to code you wrote yourself.
note that you can now use tonum("aa",1)
to convert a byte (two hex chars) to a number!
Lately I've been encoding nybbles as 0123456789:;<=>?
, which is 16 sequential characters in ascii/p8scii order, so that I can use ord(s,i)-48
(because ord("0")
is 48) to get the nybble's value without extracting/creating substrings. This has the downside that the nybble-encoded data isn't as readable (unless you memorize the new "digits" for A-F/10-15), but it simplified a lot of my code.
For instance, if I were to specialize your function for bytes:
function hexbytetodecimal(b) local a={} for i=1,#b,2 do -- -816 == -48*16-48 add(a,ord(b,i)*16+ord(b,i+1)-816) end return a end |
This is also nice for unpacking to memory, you just replace the table add with a poke.
Similarly, you'd build up such a string with b..=chr(byte>>>4|48)..chr(byte&15|48))
.
Thanks!
I've created a new thread about tonum()!
https://www.lexaloffle.com/bbs/?tid=42448
Oh! That's an interesting measure!
If split() has a strict CPU cost in the future, you should consider using it.
[Please log in to post a comment]