Android Question For Each x as y in Z

Robert Valentino

Well-Known Member
Licensed User
I love using For Each to do my looping, mainly because it is so much more readable

Is there anyway to find out what iteration we are at?

I find myself having to do
B4X:
for i = 0 to Z.size-1
    x = Z.get(i)
next
Just so I can have an index (iteration) of where we are at.

For Each must be maintaining some type of internal index to be able to move on to the next entry

Can reference the internal index from within the For Each statement?

Thanks

BobVal
 

Robert Valentino

Well-Known Member
Licensed User
No, not progressbar just looping a list of players and sometimes I need to know where I am in the list

I know create a new function:

Where I is the name of a variable to be used

B4X:
For Each X as Y in Z using I
     if  X.PlayerName = "John" then
         Log("Entry:" &I &"  Is John")
     end if
Next
LOL, yeah that is going to happen
 

ilan

Expert
Licensed User
No, not progressbar just looping a list of players and sometimes I need to know where I am in the list

I know create a new function:

Where I is the name of a variable to be used

B4X:
For Each X as Y in Z using I
     if  X.PlayerName = "John" then
         Log("Entry:" &I &"  Is John")
     end if
Next
LOL, yeah that is going to happen
try this:

B4X:
    Dim index As Int = 0
    For Each X As Y In Z
        If  X.PlayerName = "John" Then
            Log("Entry:" & Z.get(index) &"  Is John")
        End If
        index = index + 1
    Next
 

MarkusR

Well-Known Member
Licensed User
its off topic but how about this style:
programming since 1984 :D

B4J
B4X:
Sub Process_Globals

   'Private fx As JFX
   'Private xui As XUI
   Public MainForm As Form
   Type TPlayer(ID As Int,Name As String,Score As Int,Selected As Boolean,Debug As Boolean)
   Public PlayerList As List

End Sub

Sub AppStart (Form1 As Form, Args() As String)

   MainForm = Form1
   MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
   MainForm.Show
   
   NewPlayer("John")
   NewPlayer("Susan")
   
   DebugPlayers
               
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
   Return True
End Sub

Sub NewPlayer(Name As String) As TPlayer

   If Name = "" Then Name = "?"

   If PlayerList.IsInitialized = False Then PlayerList.Initialize

   Dim PlayerX As TPlayer

   PlayerX.Initialize
   PlayerX.ID = PlayerList.Size + 1
   PlayerX.Name = Name
   PlayerX.Debug = True
   
   PlayerList.Add(PlayerX) '<- Global List

   Return PlayerX

End Sub

Sub DebugPlayers

   For Each X As TPlayer In PlayerList
       If  X.Debug = True Then
           Log($"Debug Entry: ${X.ID} ${X.Name}"$)
       End If
   Next
 
End Sub
 

Robert Valentino

Well-Known Member
Licensed User
if you need to resort the list then you have loop the list just to set the index.

Normally I am just doing
B4X:
For I = 0 to playerlist.size-1
Next
But I just like the looks of for each

Looking at the java code generated by "for each". He is generating a index to use.

so in theory my idea of a "for each x as y in z using i" is possible
 

MarkusR

Well-Known Member
Licensed User
why not resort like this?
B4X:
PlayerList.SortType("ID",False)
 

Robert Valentino

Well-Known Member
Licensed User
In your example the I'd is the index into the list. but you sort by name, or zipcode or anything else the I'd needs to be reset

But I think we have gone from something about readable to a coding example
 

Robert Valentino

Well-Known Member
Licensed User
My desire is pure looks.

Using your example (assuming you had other fields in you type)

B4X:
dim Entry as int
dim player as TPlayer

PlayerList.SortType("ZipCode", false)

for Entry = 0 to PlayerList.Size-1
  player = PlayerList.get(Entry)

  if  player.Name = John then
      ' Do something like move this entry
  end if
next
Now doing it with a For Each

B4X:
PlayerList.SortType("ZipCode", false)

for each player as TPlayer in PlayerList
  '  Do something with player
  '  Not knowing the Index of where we are at I cannot move the entry or do some other things
next
So let's do it

B4X:
dim Entry as int = 0

PlayerList.SortType("ZipCode", false)

for each player as TPlayer in PlayerList
  '  Do something with player
  Entry = Entry + 1
next
Next doing it with for each

Now I know under the covers the compiler is generating an Index to reference the table entries.
I am just saying why not let us share the index

B4X:
PlayerList.SortType("ZipCode", false)

for each player as TPlayer in PlayerList using Entry
     '  Now we are looping the players and using or sharing "Entry" with the compiler
next
If you want even more syntax (for readability only)

B4X:
PlayerList.SortType("ZipCode", false)

for each player as TPlayer in PlayerList using Entry as index
     '  Now we are looping the players and using or sharing "Entry" with the compiler
next
This was just a thought.

I am always trying to make my code more readable (just an old fart that cannot change their ways LOL)

Thanks for all the input
 

emexes

Well-Known Member
Licensed User
Now I know under the covers the compiler is generating an Index to reference the table entries.
That might be true for array-like containers, but is probably untrue for iterating through linked list or tree or file directory structures, or anything dynamic.

I am just saying why not let us share the index
I am guessing that it's because, if an index is available, then using For I = 0 to NumItems - 1 is not particularly onerous. Although I suspect also maybe because there would be substantial support time consumed in repeatedly explaining why the index is not consistently available.

I am quite happy that Anywhere Software is focusing their resources on areas that have the greatest leverage ie Our_Results / Their_Effort. Like, I'd love to have INCR and DECR operators (particularly since they are natively supported by the JVM) but... am we better off with those, or with some other useful feature that we can't already easily do another way?
 

emexes

Well-Known Member
Licensed User
B4X:
for each player as TPlayer in PlayerList using Entry as index
     '  Now we are looping the players and using or sharing "Entry" with the compiler
next
This was just a thought.
That is quite a good-looking thought, though ;-)

No complaints from me if it gets implemented.

But...

If you want the index so that you can use PlayerList.Get(Entry), then what is the point of having player, which refers to the same object?

Perhaps we could remove the redundant reference and simplify it down to something like:

B4X:
For Entry = 0 to PlayerList.Size - 1
Hang on a second... I feel like I've seen that before somewhere ;-)

edit: fixed typo TPlayer s/b player
 
Last edited:

Robert Valentino

Well-Known Member
Licensed User
Not sure what you mean. In this case TPlayer is a Type that could have 30+ fields in it.

I am sure that I am not explaining myself properly.

I either do my loops with the for i = 0 to ... if I need to be able to do a Get from the List otherwise I do a for each if I don't.

But sometimes I find after I have written a for each loop that I actually need to know where I am in the table (for whatever reason it may be)

This is strictly something I thought would be a easy add on to for each

You said:
"That might be true for array-like containers, but is probably untrue for iterating through linked list or tree or file directory structures, or anything dynamic."

I didn't realize that for each was smart enough to follow a link list array (have only used standard arrays and lists)
 

MarkusR

Well-Known Member
Licensed User
Not knowing the Index of where we are at I cannot move the entry or do some other things
what do you mean with move and other things?
a own sort number beside the ZipCode?
 

emexes

Well-Known Member
Licensed User
Not sure what you mean. In this case TPlayer is a Type that could have 30+ fields in it.
You're right, bit of an unfortunate typo. Fixed.

This is strictly something I thought would be a easy add on to for each
It is easy for array-like structures where the address and index are related, but not so easy for other structures.

I didn't realize that for each was smart enough to follow a link list array (have only used standard arrays and lists)
eg Activity.GetAllViewsRecursive
 

ilan

Expert
Licensed User
dim Entry as int
dim player as TPlayer

PlayerList.SortType(
"ZipCode", false)

for Entry = 0 to PlayerList.Size-1
player = PlayerList.get(Entry)

if player.Name = John then
' Do something like move this entry
end if
next
what do you mean with move the entry

if you use "for i = 0..." you cannot move the entry from 1 position to another because the whole loop will not work as expected.

ps. if you set an integer before the loop and increase it on each step you will have the position where you are so you can do the same thing as you do in your loop.

note that for each.. will also go through the loop from 0 to list.size-1 as it goes via for i = 0 to...
from what i know for each is faster then for i ...

the question is really what you are doing in your loop and what you mean with move the item. you can do anything in a for each loop like you do in a for i loop.
 

rgarnett1955

Member
Licensed User
The hard things are easy in Java, the easy things are hard.

Why can't Java do: Hard = easy, Easy = easy?

That's why I've never bothered to learn it.

I guess if I was 20 instead of 65 I could do it.

Best regards

Rob
 

MicroDrie

Active Member
Licensed User
Why can't Java do: Hard = easy, Easy = easy?
Because of the same mistakes I regulatory made while I try to improve my Java skills, forget 🤔 the ; character at the end of the Java statement? Yes, man for the young programmers (in their twenties :cool:) from the seventies the years are really going to count now. 😂

Best regards,
Ruud
 
Top