Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

[Solved] Finding a class from a list by using one of its variables

Discussion in 'Scripting' started by dragriff, Feb 25, 2020.

  1. dragriff

    dragriff

    Joined:
    Oct 22, 2015
    Posts:
    39
    Greetings!
    I have a very specific kinda question that I am not even sure how to look up.

    So basically, I have a class in my script, which has multiple variables in it, say, something like this:

    Code (CSharp):
    1. public class CustomClass
    2. {
    3.        public int customInt;
    4.        public CustomEnum customEnum;
    5. }
    And I have this class in a list, like this:
    Code (CSharp):
    1. public List<CustomClass> customClassList = new List<CustomClass>();
    Now, my question is: Is it possible to find a specific class out of that list, by comparing one of its variables, like the enum?

    Say, I wanna find the class that has the customEnum set to: customEnumSelectionThree
    How would I go about doing something like this?

    Thank you!
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,748
    There's a couple of ways. One is to use LINQ, which is designed for this sort of query.

    You could loop through your list:
    Code (csharp):
    1. foreach (var item in customClassList) {
    2. if (item.customEnum == CustomEnum.SomeValue) {
    3. //do something with item
    4. }
    5. }
    If there's always only one item associated with a particular enum value, you could use a Dictionary rather then a List:
    Code (csharp):
    1. Dictionary<CustomEnum, CustomClass> dict = new Dictionary<CustomEnum, CustomClass>();
    2. dict.Add(CustomEnum.SomeValue, item);
    3. Debug.Log("The int is "+dict[CustomEnum.SomeValue].customInt);
     
  3. dragriff

    dragriff

    Joined:
    Oct 22, 2015
    Posts:
    39
    Hello! Thank you for your reply!

    Yeah, I was considering using a for loop, but was wondering if there maybe existed a more direct method.
    Dictionary seems like something I could potentially use, but I feel like I might do it with a for loop instead.

    Thank you!
     
  4. ServantOMallard

    ServantOMallard

    Joined:
    Aug 17, 2018
    Posts:
    14
    Using Linq you can do the following:

    Code (CSharp):
    1. CustomClass foundItem = (from item in customClassList where item.customEnum == CustomEnum.SomeValue select item).FirstOrDefault();
    2.  
    3. if (foundItem != null)
    4. {
    5.     // Do something...
    6. }
     
  5. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,204
    Or you can use Linq, but not use it's insane special syntax:

    Code (csharp):
    1. var foundItem = customClassList.FirstOrDefault(item => item.customEnum == CustomEnum.SomeValue);
     
  6. ServantOMallard

    ServantOMallard

    Joined:
    Aug 17, 2018
    Posts:
    14
    Where's the fun in that? ;)
     
    Baste likes this.
  7. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,204
    On a serious note, that special syntax ends up making you write code that's horrible for performance by default.

    In this example, my version takes the first element it finds that matches the predicate. Your version allocates a collection of some sort (maybe with a lazy wrapper around it), puts every element that matches the predicate into that collection, and then withdraws the first element.

    If you wrote a for-loop that did that it'd be utterly obvious that it was insane, but that's just the kind of code that tends to happen in the (from x in y where blah) syntax.
     
    ServantOMallard likes this.
  8. ServantOMallard

    ServantOMallard

    Joined:
    Aug 17, 2018
    Posts:
    14
    Interesting, I didn't know that. I come from a more data-driven software background so have always found the SQL query-like syntax easier to read. I'll use this from now on, thanks!
     
  9. dragriff

    dragriff

    Joined:
    Oct 22, 2015
    Posts:
    39
    Thank you for your replies!

    So that's interesting. I saw something about these Linq things, but had no idea how to use them.

    My code now looks kinda like this:
    Code (CSharp):
    1. var foundItem = classList.FirstOrDefault(item => item.customEnumType1== CustomEnum.customEnumType1);
    2.  
    3. int test = classList.IndexOf(foundItem);
    It now gets the index of that list item, which is ultimately one of the things I wanted.

    But before I run off, is there anything I need to know about this Linq method? Is it okay to use for mobile games? Is it one of the cheapest on performance ways of doing it? Something else?


    Thank you for your help!
     
  10. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,204
    If you wanted the index, you should use a method that does that. Right now you're looking through the entire list for a thing that matches your enum, then you look through the entire list again with indexOf to find the thing you were just looking for. That's a waste.

    List has a FindIndex method you should use instead:

    Code (csharp):
    1. var foundItemIndex = classList.FindIndex(item => item.customEnumType1== CustomEnum.customEnumType1);
    Depends on how often you call it. Linq (and all other ways of coding that uses a bunch of lambdas (ie. the
    x => y
    stuff) allocate a bunch of garbage memory each time you do the call, as the lambda is wrapped in an object.

    If you want that piece of code to be as performant as possible, there's nothing you can do that beats a for-loop.
     
  11. dragriff

    dragriff

    Joined:
    Oct 22, 2015
    Posts:
    39
    Ah, alrighty, thank you for the info!