Nested For loop

From StealthBot Wiki
Jump to: navigation, search

Nested For...Next loops are where it starts to get tricky, but it's not that tricky once you understand how it works.

Nested executing order

When I was first starting out how to script, I had to learn this for myself and it took me a while to put what I'm looking at into words, so here you go for free. :P A nested loop is a loop within a loop.

For i = 1 To 5
    For j = 1 To 5
        ' code
    Next
Next

Say we're counting with two variables, i and j, here's how the nested loop will evaluate the inner code:

  1. Loop to first i value (in this case, 1)
    • Evaluate the code for j from start to end (1 through 5)
  2. Loop to second i value (2)
    • Evaluate the code for j from start to end (1 through 5)
  3. Loop to third i value (3)
    • Evaluate the code for j from start to end (1 through 5)
  4. and so on...

The above loop example will execute 25 times.

Matching

Keep in mind that this is a very generic case, but this is more than likely how it's working. The best way to explain this is a real world situation.

You have two lists: a clan list from two weeks ago and a clan list you just updated or retrieved. Here are the lists:

  1. 2-week old clan list:
    • User1
    • User2
    • User3
    • User4
    • User5
  2. Updated clan list:
    • User1
    • User2
    • User3
    • User4
    • User5
    • User6
    • User7
    • User8

Your goal is to evaluate the new list to see who's existing and who is new...nested for loops!! Let's just addchat all the variables with a simple check to notify us if they exist or if they don't exist. Note that for each loop, the counter variables MUST be different. Example, you can't have For i = ... inside another loop that's For i = ....

oldList = Array("User1", "User2", "User3", "User4", "User5")
newList = Array("User1", "User2", "User3", "User4", "User5", "User6", "User7", "User8")

'// Remember that arrays start at 0 and UBound(array) returns an integer, so this is really saying:
For i = 0 To UBound(newList)
    For j = 0 To Ubound(oldList)
        AddChat 151223, "(i) " & newList(i) & " : " & "(j) " & oldList(j)
        AddChat vbMagenta, "Does " & newList(i) & " match " & oldList(j) & "?"
        AddChat vbGreen, newList(i) = oldList(j)
    Next

Next

I'll let you study the output for yourself. Notice that as the i variables progressed, there were points where they didn't change, only the j variables were changing. This is because of what I said earlier: for every i</ocde> value, all the <code>j values are looped through before the i counter can increase, squaring the length of the loop.

You'll have to add in an If block to do something when you find that the new user is found or an old user is not found.

Sorting

Now, let's look at how we can set up a bubble sort to arrange some clan user's inactivity days in ascending order (least inactive to most inactive). It is still the same process as above: nested loops, but we're going to be using some variables to get some control on this loop because we don't want some wild loop happening, we want this double loop to not overwrite everything as it goes on.

Script("Name") = "SortTester"
Script("Author") = "The-Black-Ninja"
Script("Major") = 1
Script("Minor") = 0
Script("Revision") = 0

Sub Event_PressedEnter(text)
    If Left(text, 2) = "/testsort" Then
        names = Array("User1", "User2", "User3", "User4", "User5", "User6", "User7", "User8", "User9", "User10")
        inactiveDays = Array(12,3,22,34,6,9,10,11,12,12)

        '// Set a variable to some really high number so that we have
        '   something to compare their times with something that we
        '   know they aren't going to exceed
        maxCount = 5000

        '// Loop through the days inactive only. This is so we can keep
        '   looping through all the days and constantly comparing if the
        '   day we're looking is higher or lower that something we've
        '   already looked at
        For i = 0 To Ubound(inactiveDays)
            For j = 0 To Ubound(inactiveDays)
                '// Check if the days in the array are less than the
                '   maxCount (obviously it will be less)
                If inactiveDays(j) < maxCount Then
                    '// Set a temporary variable to reflect the loop
                    '   counter we observed the result at
                    num = j
                    '// Set the maxCount variable equal to the current
                    '   value of the array for the loop counter. This
                    '   is so that as the loop goes on and on, our
                    '   maxCount will get smaller and smaller until it
                    '   can't get any smaller. Once it reaches that point,
                    '   we have the lowest value and we can proceed.
                    maxCount = inactiveDays(j)
                End If
            Next
            '// We found the smallest value, so set it into out little
            '   output before we move on
            output = output & names(num) & " (" & inactiveDays(num) & "), "

            '// Temporarily alter our item so that we are setting the
            '   lowest number we found equal (or greater) than the maxCount
            '   so when we loop over it again, we won't be overwriting our
            '   lowest value with something we already found
            inactiveDays(num) = 5000

            '// Finally, reset our maxCount because we messed with its
            '   value earlier and so that we can continue comparing values.
            maxCount = 5000
        Next

        AddChat vbGreen, "Inactive users: " & Left(output, Len(output) - 2)
    End If
End Sub

If you're confused about this, you should add a few AddChat() calls in throughout the loop so you can visually see how it's all working. It still takes me a few minutes to visualize what I'm trying to do if I haven't done this for a while, so don't feel bad if you can't understand it right away :).

This information was originally written by TheBlackNinja.

See also