Growing arrays
BlitzMax Forums/BlitzMax Programming/Growing arrays
| ||
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. |
| ||
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 |
| ||
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 |
| ||
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. |
| ||
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? |
| ||
' 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" |
| ||
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 |
| ||
Or, add the tiles into a 2d array of tiles :) |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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) |
| ||
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. |
| ||
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. |
| ||
TList sounds like the go. Thanks for clearing this up Dream & Tony. |
| ||
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. |
| ||
or maps Hmm...TMaps are similar to TLists? I haven't yet used TMaps. |