Log In  

Quick question. I'm working on a bit of a text library and wondered if there is a way to use SPLIT where it starts with base zero ?

cls()
col=split("10,9,8,4")
for i=1,4 do
  ?col[i]
end

To something like this:

cls()
col=split([0]="10,9,8,4")
for i=0,3 do
  ?col[i]
end

?

P#99644 2021-11-05 20:35 ( Edited 2021-11-05 20:36)

Looking at the documentation, it doesn't seem like it. If you have control over how your strings are created though you could just put the "first" (zero indexed) element at the end of the string then do something like this:

col=split("9,8,4,10") -- 10 will end up in index 0
col[0] = col[#col]
col[#col] = nil

This should still save you tokens in general. (Assuming your lists are going to be longer than 4 elements.) Not ideal but it'll get the job done if working with 1-based arrays really isn't an option.

If you don't have control over how your strings are created then this may not be an option.

P#99645 2021-11-05 20:52

Hi @jasondelaat:

Thanks for writing !

Checking ...

That does indeed work. Complex. Is there a way that uses less tokens ?

Zero base is not an option, I've just always felt more comfortable starting every array with zero.

I know I can use:

col={[0]=10,9,8,4}

However SPLIT() is a command I just recently learned so I'm trying to master it - to see if I can get a zero base out of it.

P#99646 2021-11-05 21:03 ( Edited 2021-11-05 21:05)

I realized a few days ago that you can swap variables like so:

a, b = b, a

And if you leave values off the right-hand side of that the corresponding values will get set to nil. So you can save a couple tokens by doing it like this:

col[0],col[#col]=col[#col]

Other than that I can't really think of a more efficient way to do it, though someone else might have suggestions.

If you have to do this often you can put it in a function so you only pay the token cost once.

function reindex(lst)
  lst[0],lst[#lst]=lst[#lst]
end

Costs a few more tokens to define and a couple tokens each time you call it. But the more often you call it, the more tokens you save overall.

P#99647 2021-11-05 21:16

I think you gave me an idea, @jasondelaat. Try out this code:

a=split("0,1,2,3")
foreach(a,shift)
for i=0,3 do
  ?a[i]
end
function shift(n)
  a[n-1]=a[n]
end

0
1
2
2

Not the right results but closer. I think for now I'll just use:
[code]
a={[0]=0,1,2,3}

I have to admit SPLIT is a lot better than what I had to do in QBASIC using INSTR() to look for "," and separate the data manually based upon its position (and count) in a string.

P#99664 2021-11-06 03:41

To reassign items in a sequence to their numeric index minus 1:

-- 17 tokens:
function shift(t)
 t[0]=t[1]
 deli(t,1)
 return t
end

-- 7 tokens, composed functionally with split():
a=shift(split("0,1,2,3"))

-- shift() modifies the table in place, so you can also do (8 tokens):
a=split("0,1,2,3")
shift(a)

If modifying in place is sufficient (as in the second example), you can remove the return statement and save two tokens.

To create a new shifted sequence without modifying the original, use this table cloning trick with unpack():

-- 13 tokens:
orig=split("0,1,2,3")
a=shift({unpack(orig)})

You probably know this, but for posterity: Lua's sequence operations all assume 1-based indexes, so the shifted "sequence" isn't really a sequence, it's a sequence with its first term removed and reassigned to non-sequence index 0.

assert(a[0] == 0)
assert(a[1] == 1)
assert(a[2] == 2)
assert(a[3] == 3)

assert(#a == 3)     -- not 4

-- prints 1 2 3
for v in all(a) do
 print(v)
end
P#99670 2021-11-06 07:10
1

One final thought on this @dw817. Building on @dddaaannn's shift function, if you're sure you always want 0 based indexes you could redefine split like so:

-- 27 tokens
_split = split
function split(...)
  local l = _split(unpack{...})
  l[0] = l[1]
  deli(l, 1)
  return l
end

And then you just use it like normal except you get 0-based arrays instead of 1-based. Including the potential downsides mentioned above.

col='1,2,3,4'

-- 5 tokens per call to split
c = split(col)

-- or 4 if called with a string literal and no parens
-- c = split'1,2,3,4'

for i=0,4 do 
  print(c[i]) -- c[4] should be nil
end

which prints

1
2
3
4
[nil]

as expected.

And it'll work with the same arguments that normal split works with, so this would also work splitting on spaces instead of commas.

col='1 2 3 4'
c = split(col, ' ')
for i=0,4 do 
  print(c[i])
end

You can decide for yourself whether redefining standard functions is a good idea or not but it is a possibility.

P#99689 2021-11-06 16:00

Oh wow, @jasondelaat. You see it's code like @dddaaannn's I can't understand with a darn. Yet that is exactly what I'm looking for. Zero base SPLIT.

Verified that the UNPACK command works with v0.2.1b. That's the cellphone version of Pico-8.

Code size has never really been a problem for me except in one of my older games. So the new SPLIT command he wrote, yes, that will do very nicely, with full credit to him.

Thanks for bringing this to my attention !

-- zero base split by dddaaannn
_split = split
function split(...)
  local l = _split(unpack{...})
  l[0] = l[1]
  deli(l, 1)
  return l
end

cls()

a=split("pears,bananas,grapes")

for i=0,2 do
  ?a[i]
end

Works beautifully !

P#99698 2021-11-06 17:39 ( Edited 2021-11-06 17:44)

pack/unpack added v0.2.0i according to the release notes. (I imagine the ... operator was always there but useless without pack/unpack. :) )

P#99699 2021-11-06 17:44
1

from the manual:
"Because table indexes start at 1, colour 0 is given at the end in this case."

when you use it for the "Pal"-Command, you can simple use position 16 as color 0.

P#99701 2021-11-06 18:10

another approach that I use sometimes:

function arr0(zero,arr)
 arr[0]=zero
 return arr
end
altpalette=arr0(0x80,split"0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f")
P#104483 2022-01-07 18:12

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2022-12-07 04:19:50 | 0.031s | Q:27