Growing arrays

BlitzMax Forums/BlitzMax Programming/Growing arrays

Chroma(Posted 2008) [#1]
Ok next obvious array question. Let's say I define an array like so:
Local MyArray:int[]


Now I want to be able to increase the array size but preserve previous array data. Say if I have:
Local MyArray:Int[] = New Int[5]

and I want to another to it to make it [6] but preserve the first 0-5 info.


Bremer(Posted 2008) [#2]
Local MyArray:Int[]

MyArray = MyArray[..5]

MyArray[0] = 10
MyArray[1] = 9
MyArray[2] = 8
MyArray[3] = 7
MyArray[4] = 6

For i = 0 To 4
	Print MyArray[i]
Next

MyArray = MyArray[..10]

MyArray[5] = 5
MyArray[6] = 4
MyArray[7] = 3
MyArray[8] = 2
MyArray[9] = 1

For i = 0 To 9
	Print MyArray[i]
Next


Look up Slices in the docs. You will find it at Help->Language->Slices


Chroma(Posted 2008) [#3]
Bah...I just came here to post that too hehe. The [..] did the trick.

I wish the BMax docs were online too.

Local array:Int[]

array = New Int[5]
array = array[..array.length+1]

For i = 0 To array.length-1
	array[i]=i+1
Next

For i = 0 To array.length-1
	Print array[i]
Next




Dreamora(Posted 2008) [#4]
One suggestion: don't do slices with +- 1
If you change it, do it always be *2 or /2 ... that will make sure it amortizes the massive costs of copying the data etc and ends with a good performance therefor.

continous +- slicing will bring your app to a total halt.


Chroma(Posted 2008) [#5]
Well the slicing is done just on the load. But just for the sake of understanding, can you give a small example of what you mean?


Dreamora(Posted 2008) [#6]
' Array Slot 0 holds the number of the next free slot in the array
' Array 'arr' resize
if arr.length < arr[0]
 arr = arr[..arr.length * 2]
endif


' Array downslice somewhere else
if arr.length > 0.35 * arr[0]
 arr = arr[..arr.length / 2]
endif


the 0.35 there is a freely choosable constant <= 0.5
I choose 0.35 because it makes sure that the array will not need to be sliced larger after few additions again by giving it a "security threshold"


Chroma(Posted 2008) [#7]
I ended up using TLists after all. I made the type have a List that contains all the items and then had a special RenderList. When I want to see an item I add it to the RenderList.

So instead looping through a hundred tiles seeing which few are to be shown with a vis flag:
For tile = Eachin TileList
   If tile.visible = True then tile.Render()
Next


I just add the tiles I want to see to this special RenderList and then remove them when they are out of play.
For tile = Eachin RenderList
   tile.Render()
Next



Czar Flavius(Posted 2008) [#8]
Or, add the tiles into a 2d array of tiles :)


Retimer(Posted 2008) [#9]

One suggestion: don't do slices with +- 1
If you change it, do it always be *2 or /2 ... that will make sure it amortizes the massive costs of copying the data etc and ends with a good performance therefor.

continous +- slicing will bring your app to a total halt.



Is this suggested mainly for loops? I use +1 slices when a user logs into a server, which might use around 10 slices once every couple minutes.


tonyg(Posted 2008) [#10]
It really is going to depend on the results.
In your case I might simply increase the size of the starting array if I have an idea how many users will logon. It might be a tradeoff between slicing too often or wasting a bit of memory by oversizing the array.
The important factor is being able to profile your program and have it be flexible enough to make simple changes.
In your case, it might not matter at all.


Retimer(Posted 2008) [#11]
I only ask because I have a hell of a lot of code that goes by the length of an array.

for i = 0 to len(<array>)-1

next


So it seems that not slicing right away would result in wasted cpu cycles, not to mention my arrays are re-indexed after being sliced (when a player logs off on index 4 when there are 20 indices, everything is re-indexed to optimize loops..including the sockets/streams).
So slicing more than 1 at a time would also cause a minor spike at run-time right? Maybe defeating the purpose and causing a freeze-up anyways.

I'm not arguing with Dreamora's comment. Instead I would just like to discuss this more so I can understand the best solution in different situations.

As for increasing the starting array for users...that wouldn't be a problem, but these users also create several projects, multiplayer sessions, resize maps, create new entities, etc. This project is a multi-user game development network, not an online game.

Any more input on this delayed slicing is appreciated.


Dreamora(Posted 2008) [#12]
The problem with slicing is that the whole old array must be copied ... this is very wastefull if you do it continously ... if you have 20 elemtns, potentially no problem.

If you do it with 100-500 elements it will seriously slow down the whole thing.


And the "wasted" time there is 0 actually. loops are lightning fast in BM and if you have an early break condition (if bla then continue ) it does not hurt at all. (few ticks only)


tonyg(Posted 2008) [#13]
If you're saying that the array is not only dynamically resized often but also reorganised to remove unused slots then you might need to be using lists or maps.


Dreamora(Posted 2008) [#14]
Yes, restructuring definitely would benefit of TList. TMaps won't help there, TMap has no changeable order, its a keybased, balanced binary tree where you only can inserst stuff, remove it, ask for it and iterate over the keys / values.


Retimer(Posted 2008) [#15]
TList sounds like the go. Thanks for clearing this up Dream & Tony.


tonyg(Posted 2008) [#16]
TMaps won't help there, TMap has no changeable order,

I didn't see any need for a changeable order though.
@Retimer, you're welcome.


Chroma(Posted 2008) [#17]
or maps


Hmm...TMaps are similar to TLists? I haven't yet used TMaps.