Removing an element from an array

BlitzMax Forums/BlitzMax Programming/Removing an element from an array

SystemError51(Posted 2012) [#1]
Hi all,

okay, so say you have an array of a defined size. Let's assume I have an array inside which I'm storing vertex coordinates, and it has some 1,200 values in it (example).

However, to do some optimizing, I'd like to know if it is possible to remove values from somewhere in the middle of the array, without having to take all values, store in another temporary array, and reconstruct the original array?

I know that I could use lists - but I was wondering if there is a way to this with arrays.


BladeRunner(Posted 2012) [#2]
I don't think this is easily possible without use of an external array. You could do sth like
for local i:int = deletepos until array.length-1
array[i]=array[i]+1
next
which removes the item and leaves the last entry doubled (can be set to 0 seperately) but I doubt that this operation will be faster / equally fast to an newarray[]=arry[..i]+array[j..] (which could be what you searched for anyway).


ImaginaryHuman(Posted 2012) [#3]
What I do when I need this is that when I remove an element from the array, I `move` the highest indexed element into that position. ie take the highest index element and overwrite the one you're removing, then just keep track of how many elements you're using. But this only works if the order of the elements doesn't matter.

If you're using a vertex array I presume you also have an `index` array... so you technically probably don't need to do anything to deal with the gaps you're creating, unless you want to optimize things by having a smaller vertex array upload?

As above, if you move the highest vertex element to overwrite the one you're removing then you just need to update any indexes in the index array that reference them.


matibee(Posted 2012) [#4]
You can't memcopy but you can memmove http://msdn.microsoft.com/en-us/library/8k35d1fx%28v=vs.71%29.aspx

An MSDN link but I'm sure this is cross platform. Although I was surprised when it compiled in blitzmax straight off, so I assume this is a function provided by the mingw compiler.

Its a bit ugly too because I don't know how to "sizeof" in blitzmax. Any enlightenments greatfully received :)

SuperStrict 

Local a:Int[] = New Int[100]
Local count:Int 
For Local i:Int = 0 To 99
	If ( i >= 30 And i <= 40 )
		a[i] = 0
	Else 
		a[i] = count
		count :+ 1
	End If 
Next 

For Local i:Int = 0 To 99
	Print i + "= " + a[i]
Next 

MemMove( (Byte Ptr a) + (30 * 4), (Byte Ptr a) + (41 * 4), 59 * 4 )

For Local i:Int = 0 To 99
	Print i + "= " + a[i]
Next 



Yasha(Posted 2012) [#5]
memcpy and memmove are C Standard Library. They'll work almost literally anywhere.


Banshee(Posted 2012) [#6]
Might I suggest a linked list instead of an array? It's much easier to manipulate them, they can have multiple properties which is handy and removing things from the list is easy.

Sadly, after years of coding php, I do sometimes find BMax frustrating with its array handling! But I guess that's what php is designed for.


matibee(Posted 2012) [#7]
Unfortunately you can't upload a linked list of vertices or indices to VRAM (but I'm sure some clever shader writers could probably prove me wrong).


SystemError51(Posted 2012) [#8]
Hi all,

I thank you all for your suggestions :) Indeed, it seems a bit tricky, but matibee's way could be one way to go about it. I'll probably ultimately ending up using some kind of other temporary array and reconstruct the original one =/


@matibee -

Its a bit ugly too because I don't know how to "sizeof" in blitzmax. Any enlightenments greatfully received :)


[bbcode]SizeOf(yourArray)[/bbcode]

:)


matibee(Posted 2012) [#9]
Actually it was sizeof primitive data types, ie sizeof( int ) I was looking for.

Just testing: "sizeof( a:int )" works ok


TomToad(Posted 2012) [#10]
Interesting, you can concatenate two arrays. Using slices, this will remove elements as well as decrease the size of the array.

SuperStrict 

Local a:Int[100]
Local count:Int

For Local i:Int = 0 To 99
	If i > 30 And i < 40
		a[i] = 0
	Else
		a[i] = count
		count :+ 1
	End If
Next

For Local i:Int = 0 Until a.length
	Print a[i]
Next

a = a[0..31]+a[40..]

For Local i:Int = 0 Until a.length
	Print a[i]
Next


Last edited 2012


col(Posted 2012) [#11]
I personally use something like...

BeforeCut[] = TotalArray[0..CutPoint]
AfterCut[] = TotalArray[(CutPoint+1)..TotalArray.Length]

TotalArray = BeforeCut + AfterCut


You can adjust the 'CutPoint' index to cut a single index out, or use 2 cutpoints to cut a whole section of indices out.

Edit:- I'm curious though as to why you want to remake the array, there may be better alternatives, just asking before you get too deep and committed already.

Last edited 2012


Nate the Great(Posted 2012) [#12]
if the order of the array doesn't matter, set the value in the middle to the last value in the array and then remove the last value of the array. This is super fast and works for anything where the order of the array doesn't matter.