B4J Question How to iterate through a list when the list size is unknown

Discussion in 'B4J Questions' started by giga, Jun 13, 2015.

  1. giga

    giga Well-Known Member Licensed User

    I am trying to iterate through a list one by one. But the size of the lists vary.

    I have tried this but I still end up with error java.lang.ArrayIndexOutOfBoundsException:


    Code:
    For a = 0 To myList.Size Step -1
    Is this possible? Any help appreciated.
     
  2. LucaMs

    LucaMs Expert Licensed User

    simply:
    Code:
    For a = 0 to myList.Size -1
    (Step 1 is implied).



    The Step can be used if you wanted to do different steps, by 2 or 3.

    "Step -1" can be used so:

    Code:
    For a = myList.Size -1 to 0 Step -1
     
    giga likes this.
  3. giga

    giga Well-Known Member Licensed User

    Thanks for the reply.
    Code:
    For a = myList.Size -1 to 0 Step -1
    Did solve the outofbounds exception. But Maybe I am using the wrong structure. If Step is set to -1 it returns ALL the IDs. If I step it to 2 it will show the first then every other one.

    My ultimate goal is to step the IDs "one by one" Is that possible using step? Or is there a better way?
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    Not sure that I understand.

    The simplest way to iterate over all items is with:
    Code:
    For Each id As Int In myList
     
    Log(id)
    Next
     
  5. giga

    giga Well-Known Member Licensed User

    Thanks for the replies. Here's what I am trying to do.

    All the lists are of various sizes. Some lists may have 4 ids others may have 10 ids etc...

    I can iterate through any of the list but the problem is (since I don't always know the size of the list) If I go beyond the size of the list it errors.OutOfBounds Exception(Understandably)

    example error when there are 4 ids.(logging them individually)

    Code:
    Log(id(1))
    Log(id(2))
    Log(id(3))
    Log(id(4))
    Log(id(5)) 'It will error here and beyond because there is no 5......

    Next
    My thought was to step the list by 1 until I reached the end of the list. Thinking it would allow me to retrieve each individual id (i.e Log(id(3)) without going outofbounds (if the list was 3 or less). But that doesn't seem to be right.

    Thanks for sticking with me.:)
     
  6. LucaMs

    LucaMs Expert Licensed User

    your id seems to be an Array, not a List.

    If you have:
    Code:
    lstID As List
    and you added the IDs:
    Code:
    lstID.Add(5)
    lstID.Add(
    53)
    lstID.Add(
    11)
    lstID.Add(
    2343)
    lstID.Add(
    22)
    then you can iterate:
    Code:
    For Each ID As Int In lstID
        
    Log(ID)
    Next
    or

    Code:
    For I = 0 to lstID.Size - 1
        
    Log(lstID.Get(I))
    Next

    [P.S. its name should be lstIDs, but I did not want to change everything :D]



    If you use an Array, you should have:
    Dim IDs(5) As Int
    and you will have 5 "locations" but indexed from 0 to 4.
    Log(IDs(0)) ' ok
    Log(IDs(1)) ' ok
    ...
    Log(IDs(4)) ' ok
    Log(IDs(5)) ' out of bound

    or

    Code:
    For I = 0 to IDs.Lenght - 1
        
    Log(IDs(I))
    Next
     
    Last edited: Jun 14, 2015
  7. giga

    giga Well-Known Member Licensed User

    LucasMs. ( Thanks Your response could not have been any faster:))

    This is the code I am working with:
    Code:
    Dim parser As JSONParser
        parser.Initialize(str)
        
    Dim root As Map = parser.NextObject
        
    Dim myList As List = root.Get("myList")
        
    Dim resSize As Int = myList.size
        
    Dim id(resSize),vote_count(resSize) As Int
        
    Dim vote_average(resSize) As Double
        
    Dim title(resSize), release_date(resSize), original_title(resSize),video(resSize) As String
        
    Dim c As Int = 0
        
    For Each colresults As Map In myList
         
    id(c) = colresults.Get("id")
         title(c) = colresults.Get(
    "title")
         vote_average(c) = colresults.Get(
    "vote_average")
         release_date(c) = colresults.Get(
    "release_date")
         original_title(c) = colresults.Get(
    "original_title")
         vote_count(c) = colresults.Get(
    "vote_count")
         video(c) = colresults.Get(
    "video")
        c = c + 
    1
        
    Next
        
    For a = 0 To myList.Size -1
        
    Log("record: " & a)
            
    Log (id(a))
           
    Log (title(a))
           
    Log (vote_average(a))
           
    Log (release_date(a))
           
    Log (original_title(a))
           
    Log (vote_count(a))
           
    Log (video(a))
            
    Log("-----------------------" & CRLF)
        
    Next
    Log(id(a) will retrieve ALL the IDS.

    But let's say I want ONLY id 4 not knowing if id 4 exists will throw error outofbounds. That's my problem.

    How do I retrieve each id(1), id(2) etc... individually without knowing what the last Id is and running into the outofbound error?
     
    Last edited: Jun 14, 2015
  8. LucaMs

    LucaMs Expert Licensed User


    If your code is correct (I don't know JSONparser):
    you know the max index you can use, resSize-1 (or myList.Size -1, it is the same).

    (Perhaps I have not understood the question :D)
     
  9. giga

    giga Well-Known Member Licensed User

    No problem, Thanks anyway.:) Where I am struggling is my list could be any number of id's. I can iterate ALL id's no matter how big the list.

    But how do I retrieve only one id out of the list(without knowing the total number of id's) in the list without running into the outofbounds.exception.

    Maybe a conditional statement to catch the end of the total id's to avoid the exception ??
     
  10. LucaMs

    LucaMs Expert Licensed User

    You could use try-catch but... if you have a List, you know how many items it has!

    If you need the fourth item (index 3):

    Code:
    If MyList.Size >= 4 Then
       FoundID = MyList.Get(
    3)
    ' or, as in your example:
       FoundID = ID(3)
    End IF

    Last try :D:

    MyList.IndexOf is a function of List; it returns -1 if the item is not found
     
  11. jmon

    jmon Well-Known Member Licensed User

    what you need to do if you have to do it with a single loop is this :
    Code:
    For a = 0 To myList.Size -1
        
    Log("record: " & a)
        
    If id.size > a then Log (id(a))
        
    If title.size > a then Log (title(a))
        
    If vote_average.size > a then Log (vote_average(a))
        
    If release_date.size > a then Log (release_date(a))
        
    If original_title.size > a then Log (original_title(a))
        
    If vote_count.size > a then Log (vote_count(a))
        
    If video.size > a then Log (video(a))
        
    Log("-----------------------" & CRLF)
    Next
     
    giga likes this.
  12. LucaMs

    LucaMs Expert Licensed User


    He sized all arrays the same length (resSize = myList.Size) #7
     
    jmon likes this.
  13. giga

    giga Well-Known Member Licensed User

    @LucaMs @jmon
    I found a workaround not sure if I should release it like this but this works for me. I am using a try-catch then log. I am downloading a json file that has different numbers of ids.
    This will check each id 0-25 and if the id has no content it will log (id is empty)

    Code:
    Try
        
    If id(0) >= a Then Log(id(0))
        
    If id(1) >= a Then Log(id(1))
        
    If id(2) >= a Then Log(id(2))
        
    If id(3) >= a Then Log(id(3))
        
    If id(4) >= a Then Log(id(4))
        
    If id(5) >= a Then Log(id(5))
        
    If id(6) >= a Then Log(id(6))
        
    If id(7) >= a Then Log(id(7))
        
    If id(8) >= a Then Log(id(8))
        
    If id(9) >= a Then Log(id(9))
        
    If id(10) >= a Then Log(id(10))
        
    If id(11) >= a Then Log(id(11))
        
    If id(12) >= a Then Log(id(12))
        
    If id(13) >= a Then Log(id(13))
        
    If id(14) >= a Then Log(id(14))
        
    If id(15) >= a Then Log(id(15))
        
    If id(16) >= a Then Log(id(16))
        
    If id(17) >= a Then Log(id(17))
        
    If id(18) >= a Then Log(id(18))
        
    If id(19) >= a Then Log(id(19))
        
    If id(20) >= a Then Log(id(20))
        
    If id(21) >= a Then Log(id(21))
        
    If id(22) >= a Then Log(id(22))
        
    If id(23) >= a Then Log(id(23))
        
    If id(24) >= a Then Log(id(24))
        
    If id(25) >= a Then Log(id(25))
      
    Catch
      
    Log("id is empty")
     
    End Try
    Thanks for all the help. If there's a better way I am open to suggestions.
     
  14. LucaMs

    LucaMs Expert Licensed User

    Sorry, I don't understand.


    The code above (your code) works?

    If so, you know that you will have id(0) to id(resSize - 1)
    Or you can check id.Length
    If id.Length will be = 10, I'm sure that you will not have id(10), id(11), ...!
     
    Last edited: Jun 16, 2015
  15. Erel

    Erel Administrator Staff Member Licensed User

    Code:
    For i = 0 To 25 'probably better: For i = 0 To id.Length - 1
     If Id(i) >= a Then Log(id(i))
    Next
     
  16. giga

    giga Well-Known Member Licensed User


    You are absolutely right! "If id.Lenght will be = 10, I'm sure that you will not have id(10), id(11), ...!"
    But the user(s) don't know how many ids there are in the list and if they select id(11) the error outofbounds appears.

    Scenario.
    1. I download a json file (this particular one only has 4ids in it).
    2. I set the code length to 10 or 25 even
    3. The user is not aware how many ids are in the list and chooses to pull up id(11)
    4. This will produce the outofbounds error because there is no 11



    The only way I can stop the error is by try-catch.

    in my example code above my list has 23ids in it.(25 is my maximum length )any id 23 and below will show the contents, If the user selects number 24 or 25. it will show (id is empty)
     
  17. LucaMs

    LucaMs Expert Licensed User

    How they "select" the id?

    You fill some view (ListView? Other?) with the IDs! Create only id.Length items!


    [If they enter the number in an EditText, validate the input inside of EditText_TextChanged, of course]
     
  18. giga

    giga Well-Known Member Licensed User

    I have a listview to view and a textbox where they specify the id they want.

    Code:
    IDText.Text  = (id(gotonum.Text))
     
  19. LucaMs

    LucaMs Expert Licensed User

    (I would avoid things like: id(gotonum.Text). Dim GoToNum As Int and then GoToNum = gotonum.text is better).

    I suppose that gotonum.Text is where the user "selects" the index of id and IDText.Text shows the choice (a label would be better).

    You need to validate gotonum.Text value, inside of gotonum_TextChanged or gotonum_FocusChanged or elsewhere, before set IDText.Text = id(GoToNum).


    [P.S. validate: I mean: If GoToNum > id.Length-1 then ... not valid]
     
  20. giga

    giga Well-Known Member Licensed User

    Good advice.

    As they say "back to the drawing board" You're Awesome for all the help. I will make the changes and see how that works:).
     
    LucaMs likes this.
Loading...