foreach loop with names printing too many times?

foreach(SCOOBJ gObject in Items){
        if(gObject.itemName.Contains(Input)){
            Debug.Log(gObject.itemName);
        }
}

This code runs after a input field is changed, with SCOOBJ being a scriptable object and Items being a List. Input is the current input field text. When running it, when I type in “B”, it gets the right items, like Bat, Bomb, etc. Though, it prints 94< times. Help?

Do you have 94 things beginning with B?

Do you perhaps intend to use the .StartsWith() method instead of the .Contains() method?

No, it repeats each name with a B in it too many times. Basically, it repeats “Bat” and “Bomb” 94 times.

I could, but I would rather have it so that it can be any part of the name.

Time to print out the number of entries in the Items collection!

Also, remove your conditional and print them all. I think you’ll find you have duplicates in that list.

Possibly you’re running the code in Update(), at which point it will run every frame.

There are 43 entries in the collection. I removed the conditional and it printed all items in the list 118 times, and the code only runs every time the Input has changed. The code for checking when it’s changed does work, too.

Did you try using for instead of foreach? How many of these names in the list have several times the input letter?

is the same script attached to many gameobjects?

No.

Also no, but I also don’t understand for loops, or generally how to use for with my code right now.

For syntax is pretty simple, even if it is visually complicated:

it is: for (a ; b; c) { ... }, where:

  • a is run once
  • b has to be true to continue (a boolean condition)
  • and c is run at the end of each loop.

Obviously the { ... } block is whatever code you want to execute for the loop.

In your case it would be:

for (i = 0; i < Items.Length; i++)
{
 var gObject = Items[i];

 // now do what you want
}

If Items is actually a List instead of array, then replace .Length above with .Count

The for loop didn’t really change anything.

I’ve also noticed that the amount of times an objects name is printed is random. It also makes it lag longer the bigger number it is.

Outside of your for loop, print something like “I’m starting.”

How many times does that print?

It does the same thing as the names.

field.onValueChanged.AddListener(delegate{CheckInputForItem(field.text);});

This is the activation code, placed in Update(). “field” being the input field.

I found it out, and man do I suck at listeners.
Since it was in Update, it was adding a new listener over an over again, making the code run multiple times.

2 Likes

Glad you got it going! The pattern I like to use for listeners uses OnEnable and OnDisable. It looks like this:

    void    OnEnable()
    {
        button.onClick.AddListener (OnButtonClick);
    }
    void    OnDisable()
    {
        button.onClick.RemoveListener (OnButtonClick);
    }

That has the added benefit of when the object gets disabled, the listener comes off automagically.