How can I find what order or element number an object is in a ForEach loop?

For my purposes I need to use a foreach and not a for loop.

            foreach(Ranged weaponToCheck in PlayerController.instance.availableGuns)
            {

                if (theWeapon.weaponName == weaponToCheck.weaponName)
                {
                    hasWeapon = true;
                    print("hasWeapon = " + hasWeapon);

                    weaponToCheck.baseWeaponPower += 10;

                }
                else
                {
                    print("hasWeapon = " + hasWeapon);

                }

            }

How can I find out what element number/ order theWeapon is in availableGuns[ ] ?

I think the only way is to just declare an index variable before the foreach, set it to 0 and then increment it after each iteration.

        int index = 0;
        foreach (Ranged weaponToCheck in PlayerController.instance.availableGuns)
        {
            if (theWeapon.weaponName == weaponToCheck.weaponName)
            {
                // Here: theWeapon == availableGuns[index]

                hasWeapon = true;
                print("hasWeapon = " + hasWeapon);

                weaponToCheck.baseWeaponPower += 10;
            }
            else
            {
                print("hasWeapon = " + hasWeapon);
            }

            index++;
        }

Every foreach can be expressed as a for or while loop.

4 Likes

Like @CodeSmile said, if you need the index, use a for loop instead.

Pro Tip: in Visual Studio, it’s very easy to convert a foreach loop to a for loop (and vice versa), just put your text cursor on the “foreach” keyword, hit Alt+Enter (or Ctrl+.) to open suggestions menu, and there you’ll find “Convert to ‘for’”

Now if you insist using a foreach, and if you’re iterating a List, you could always get the index of an item by using var index = myList.IndexOf(item); but it will do a search (a for loop) to find your item index… so basically you’re doing a nested for loop for no reason…

2 Likes

If I only had a dollar for every foreach() that I ended up refactoring as a for() loop!

foreach() is “cute,” sorta in the ballpark of “kinda nice if it works for you.”

If it helps, think of foreach() as more the domain of opaque set / collections operations done by compsci teachers: simple example set operations involving absolutely nothing else of relevance regarding the collection or any other collection.

But a good old for() is where the actual meat and potatoes work gets done, especially in agile complex tightly-bound gamedev coding. You almost always end up needing to know offsets and indices, even in managed code land, just because often there is an importance to ordering or numbering that simply doesn’t exist to the theoreticians scribbling on the blackboards. :slight_smile:

Keep these two tools in mind and be ready to swap effortlessly between the two of them.

Remember: underneath it all, it’s just a code loop controlled by something.

1 Like

OP could be going through a linkedlist, where using L is an expensive O(n). Sure, one could rewrite as a FOR and manually create and move the iterator, with i=i.next(); and so on, but that still wouldn’t get the index.

You can do it with the following code just be aware that it will be slower because it’s now going to have to search through the array or list to find the index you could have been tracking with a for loop.

var index = Array.IndexOf(PlayerController.instance.availableGuns, theWeapon);

Here’s the variant for Lists.

var index = List.IndexOf(PlayerController.instance.availableGuns, theWeapon);

Meanwhile here’s your code using a for loop (change Length to Count for a List).

for (var index = 0; index < PlayerController.instance.availableGuns.Length; index++)
{
    if (theWeapon.weaponName == PlayerController.instance.availableGuns[index].weaponName)
    {
        hasWeapon = true;
        print("hasWeapon = " + hasWeapon);

        PlayerController.instance.availableGuns[index].baseWeaponPower += 10;
    }
    else
    {
        print("hasWeapon = " + hasWeapon);
    }
}

Maybe but it’s very uncommon to see anyone using the LinkedList type as it’s almost never touched on in tutorials.

1 Like

Generally I use foreach only when it’s not possible to use a for loop (IEnumerable). In all other cases (indexable collections), I use a for by default. As a (tiny) bonus: for loops are significantly faster than foreach in Lists.

This was a huge eye opener, and a huge help. Thank you! Basically (short answer) resolved my problem.

If it helps, think of for () as more the domain of opaque set / collections operations done by compsci teachers…

All you really need is a Branch Not Equal instruction, and a flags register updated on each increment.