How to keep track of EachIn loop counter?

BlitzMax Forums/BlitzMax Programming/How to keep track of EachIn loop counter?

ImaginaryHuman(Posted 2005) [#1]
When I use EachIn for a loop counter, is there some way to access where in the array/list the loop currently is?

ie

Local myarray:mytype[50]
Local counter:mytype
For counter=EachIn myarray
   Print counter
Next

Should this display indexes in the array (0..49) or should it display pointers to each instance of the type?

If you use EachIn for the looping, how can you know what position you are currently at in the array?


Beaker(Posted 2005) [#2]
That code won't work at all.

The easiest way is to have a field that you set to the index of the array when you create each object.


Yan(Posted 2005) [#3]
If you need to keep track of the current index of an array then why use EachIn?

Type mytype
	Field fred
End type

Local myarray:mytype[50]

For counter = 0 Until myarray.length
	myarray[counter] = New mytype
	myarray[counter].fred = counter
Next 

For counter = 0 Until myarray.length
	Print counter + " = " + myarray[counter].fred 
Next
Or have I got the wrong end of the stick?


Beaker(Posted 2005) [#4]
Yes, you could do it that way, but if you have a large (but sparse) array then my suggestion would be faster.


ImaginaryHuman(Posted 2005) [#5]
Cus EachIn is faster.


Curtastic(Posted 2005) [#6]
.


FlameDuck(Posted 2005) [#7]
If you need to keep track of the current index of an array then why use EachIn?
A even better question might be "Why do you need to know the index at all"? Does it matter?


Tom(Posted 2005) [#8]
Why not just use a var?
Local myarray:mytype[50]
Local counter:mytype
Local index:Int=0

For counter=EachIn myarray
  index:+1
  Print index+": whatever"
Next


Neville:
For counter = 0 Until myarray.length
Should be:
For counter = 0 Until myarray.length-1

Arrays are 0 based remember :)


Tom


skidracer(Posted 2005) [#9]
Until doesn't process the last element remember :)


Tom(Posted 2005) [#10]
owned! :)


Yan(Posted 2005) [#11]
Is EachIn the fastest way to step through an array?

I thought it was there more for convenience than speed and Blitz was just stepping through the array and returning any non NULL values [edit for clarity]to save you having to do it manually[/edit].

How are arrays stored then?


Sorry if these seem like daft question. I'm just curious.


Oh...;op @ Tom ;o)


Beaker(Posted 2005) [#12]
Squatting - my mistake, I was under the impression that arrays were cleverer or that I was using Blitz3D! :P

This works:
Type mytype
	Field x,y
End Type

Local myarray:mytype[50]

For counter = 0 Until myarray.length
	If Rand(1,5) = 1 Then  	
		myarray[counter] = New mytype
	EndIf
Next 

For counter = 0 Until myarray.length
	If myarray[counter]
		Print counter + " = " + counter 
	EndIf
Next



ImaginaryHuman(Posted 2005) [#13]
I don't know results overall but in my case I found that changing from a For counter=0 to whatever loop, to a For mytype=EachIn myarray loop, gave about a 12-15% speedup.

It is my *guess* that if you access an array individually for each iteration of the loop, using an index counter as the loop counter (or with a separate variable), each time you access the array it has to take the base address of the array, multiply (or shift) the size of the array type by the index variable, and add it to the base, before it can read the actual content. With the EachIn command, it *probably* can bypass a lot of that be just setting up the base address first and then, for every loop, add the size of the type to it. Much easier and quicker. That probably gives a speedup. Not sure how it works for linked lists though.

I just was wondering if there was some way that you could know where the EachIn had got to in the array. There are useful reasons to be able to react to the loop counter. Obviously you can use a loopcounter as in For counter= bla bla bla, but then you can't use EachIn and you lose the speed gain.

What do you mean I can't eat my own cake?


StuC(Posted 2005) [#14]
I did some timings, and didn't see the percentages you saw.

I tried the .length method directly in the for/until statement, copying it to a local var and using the local var in the for statement and also using the For/EachIn.

Try this and see how you go (will only work on Win32, as I used the RDTSC, via QueryPerformanceCounter).

A useful piece of code in there is the TCodeTimer class, which gives you an accurate nano-second timer (dependant on CPU speed). I saw some of you asking for a better than millisecond timer, so I thought I'd provide this.