Search Unity

Sum up a list

Discussion in 'Scripting' started by NotMyUsernameAgain, Dec 6, 2018.

  1. NotMyUsernameAgain

    NotMyUsernameAgain

    Joined:
    Sep 28, 2017
    Posts:
    139
    Hi everyone,

    so I have a list which contains a string value for "color" and a int value for "amount".
    (It also contains other values, but they are not important for my question).

    What I want to do is to get a result of how many amount of one color exists in the list.
    Eg.:
    I tried storing the list in a temporary list, sorted them by color and iterated through it.
    However I couldn't get it working, so I was wondering if someone on the forum could help me.

    Thanks in advance
     
  2. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    Here is a method which does what you need. (you have to replace "MyType" with the type which holds the color and amount values)
    Code (CSharp):
    1. static int GetTotalAmount(List<MyType> list, string color)
    2. {
    3.     int result = 0;
    4.     foreach(var itm in list)
    5.     {
    6.         if(itm.color != color)
    7.             continue;
    8.  
    9.          result += itm.amount;
    10.     }
    11.  
    12.     return result;
    13. }
    then you can do it like this:
    Code (CSharp):
    1. int redItems = GetTotalAmount(List, "red");
    2. int blueItems = GetTotalAmount(List, "blue");
     
  3. NotMyUsernameAgain

    NotMyUsernameAgain

    Joined:
    Sep 28, 2017
    Posts:
    139
    The problem is I never know how many colors the list contains.
    That was my actual problem.
    (sorry, forgot to mention it in my previous post)
     
  4. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    ok, then lets find out what color strings the list contains. To do so, make sure that you have a using for Linq at the top of your file first:
    using System.Linq;


    Then you can use this code:
    Code (CSharp):
    1. // A HashSet is a collection which will never have the same value twice.
    2. // lets extract the values of colors with linq and make sure every color exists once (-> HashSet)
    3. HashSet<string> colors = List.Select(o => o.color).ToHashSet();
    4.  
    5. // now we have all the colors.
    6. // Lets store the amount in a dictionary, so we can look it up.
    7. // Maybe you need it differently,
    8. // but with a dictionary you can retrieve pretty much everything you need.
    9. Dictionary<string, int> colorAmounts = new Dictionary<string, int>();
    10. foreach(string col in colors)
    11. {
    12.     int amount = GetTotalAmount(List, col);
    13.     colorAmounts.Add(col, amount);
    14. }
    15.  
    16. // maybe you want to just log the colors...
    17. // that could be done in the previous step.
    18. // But it is also possible with the Dictionary.
    19. foreach(string key in colorAmounts.Keys)
    20. {
    21.     Debug.LogFormat("{0}x {1}", colorAmounts[key], key);
    22. }
     
  5. NotMyUsernameAgain

    NotMyUsernameAgain

    Joined:
    Sep 28, 2017
    Posts:
    139
    OK, I copied the code and replaced "List" with my list and "o.color" with the name of my color string.
    (Also added the namespace "using System.Linq;")

    However, VisualStudio underlines :

    .ToHashSet()
    (contains no definiton)
    and
    GetTotalAmount (doesn't exists in the context)
     
  6. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,735
    You can use Linq to do it like this:-

    Code (CSharp):
    1.     struct MyType
    2.     {
    3.         public string color;
    4.         public int qty;
    5.     }
    6.  
    7.     List<MyType> myList = new List<MyType>() {
    8.         new MyType() { color = "red", qty = 2 },
    9.         new MyType() { color = "blue", qty = 3 },
    10.         new MyType() { color = "red", qty = 1 }
    11.     };
    12.  
    13.     void Start()
    14.     {
    15.         Debug.Log(myList.FindAll(item => { return item.color == "red"; }).Sum(item => { return item.qty; }));
    16.     }
    This is just an example of how to construct the Linq statement to find and sum, you'll need to substitute MyType with your own type and adapt the Find() and Sum() parts of the Linq statement to work with the fields in your type.

    Also remember to add using System.Linq; at the top of your script.
     
    Last edited: Dec 6, 2018
  7. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    Maybe you are using an older or smaller scripting backend for your project... you can also do it like this:
    HashSet<string> colors = new HashSet<string>(List.Select(o => o.color))


    It is the method I posted in my first reply. Either copy that to your class or use your own implementation instead (or the Linq approach which @Munchy2007 suggested).