Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Anxo · Feb 23, 2015 at 06:21 PM · arraylistdictionarylist of lists

Nested Dictionary Change Value Problem

Hi Unity Community, thank you for looking at my post. I will get str8 to the point. I have having an issue with changing, the values in a nested Dictionary, There are no errors and most of it works as expected but it does not respect a particular key and changes the value for all entries.

I have set up a test that replicates my problem, if you run this class and then hit "A" you will see a debug output of the dictionary as I set it up (all as expected). Then you hit "B" and it will change the values of the dictionary in a very specific way. BUT ONLY for a specific day!, then you hit "C" and what you will find is that it changed the value for every day, ignoring the key for the day.

Here is the class. Sorry to include your name @aldonaletto but this seams right up your ally. Any idea?

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class TestScript : MonoBehaviour
 {
 
     //The Master Dictionary to hold <location < day index < hour index < price>>>> 
     Dictionary <string,Dictionary<int,List<int>>> priceByHour;
 
     //The defualt price, value to change. 
     private int defaultPrice = 3;
 
     void Start ()
     {
         // Initilazing master Dictionary
         priceByHour = new Dictionary<string, Dictionary<int, List<int>>> ();
 
         // The locations
         List<string> locations = new List<string> {"NY"};//, "LA", "Chenarous", "Azaroth", "York", "Lancaster"};
         foreach (string loc in locations) {
 
             //Create Hours List with the prices
             List<int> hours = new List<int> ();
             for (int i = 0; i < 24; i ++) {
                 hours.Add (defaultPrice);
             }
 
             // Create Days list with the hours and prices
             Dictionary<int,List<int>> days = new Dictionary<int, List<int>> ();
             for (int i = 0; i < 7; i ++) {
                 days.Add (i, hours);
             }
 
             // add it all to the master dictionary.
             priceByHour.Add (loc, days);
         }
     }
 
 
     // To Test and review;
     void Update(){
         //Print out the content of the master dictionary
         if (Input.GetKeyDown (KeyCode.A)) {
             PrintOutMasterDictionary();
         }
 
         // change the values
         if (Input.GetKeyDown (KeyCode.B)) {
             ChangeValuesOfDayTwo();
         }
 
         // print againg to compare result
         if (Input.GetKey (KeyCode.C)) {
             PrintOutMasterDictionary();
         }
         // Notice that the dayToChange was set to index 4 but it changed the value of every over after the 6th hour to the new price! 
     }
 
 
     // Print out the result to compare after the change.
     void PrintOutMasterDictionary ()
     {
         foreach (KeyValuePair<string,Dictionary<int,List<int>>> masterEntry in priceByHour) {
             Debug.Log ("Location = " + masterEntry.Key);
             foreach (KeyValuePair<int,List<int>> day in masterEntry.Value) {
                 Debug.Log ("Day = " + day.Key.ToString ());
                 for (int i = 0; i < day.Value.Count; i ++) {
                     Debug.Log ("Hour = " + i.ToString () + " has a value of " + day.Value [i].ToString ());
                 }
             }
         }
     }
 
     void ChangeValuesOfDayTwo(){
 
         // set change perameters
         int dayToChange = 4;
         int newPrice = 5;
         string locationToChange = "NY";
         int hourToChangeBehind = 6;
 
         //Iterate through all possible hours
         for (int i = 0; i < 24; i++) {
             // if the hour is greater than hour to change, change the value
             if(i > hourToChangeBehind){
                 priceByHour[locationToChange][dayToChange][i] = newPrice;
             }
         }
     }
 }
 


Thank you.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by steakpinball · Feb 23, 2015 at 08:51 PM

This behavior occurs because List is a reference type. Reference types are simply pointers to memory. When you pass them to a method only the reference is copied. It still points to the same object. This means the loop on line 31 is making a dictionary where all values are the exact same list. Not copies. You need to either copy the list or make a new one for each day.


Value Types and Reference Types

https://msdn.microsoft.com/en-us/library/t63sy5hs.aspx

Value vs. Reference Types in C#

http://www.albahari.com/valuevsreftypes.aspx

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Anxo · Feb 23, 2015 at 09:16 PM 0
Share

wow, this is getting very confusing. According to these articles, all Arrays are reference types? So I could not solve this issue by simple avoiding the LIst and replacing with with another Dictionary? like so?

 // Before
 
  //The $$anonymous$$aster Dictionary to hold <location < day index < hour index < price>>>> 
      Dictionary <string,Dictionary<int,List<int>>> priceByHour;
 
 // After
 
  
      Dictionary <string,Dictionary<int,Dictionary<int,int>>> priceByHour;

I assume its not going to be that easy?

Its wired that there would be a problem around line 31 as when I run the test and hit A the first time, the master dictionary populated properly, but you are saying its not actually storing it but merely holding it in memory and to solve it I would have to copy the List out before I apply it like so?

 // Before...
 
 
  // Create Days list with the hours and prices
              Dictionary<int,List<int>> days = new Dictionary<int, List<int>> ();
              for (int i = 0; i < 7; i ++) {
                  days.Add (i, hours);
              }
 
 
 // After
 
  // Create Days list with the hours and prices
              Dictionary<int,List<int>> days = new Dictionary<int, List<int>> ();
              for (int i = 0; i < 7; i ++) {
                  days.Add (new $$anonymous$$eyValuePair<int,List<int>>(i, hours));//<-- or did you mean I need to move it out of that for loop because it always considers the i as the same int?
              }

avatar image steakpinball · Feb 23, 2015 at 09:34 PM 2
Share

When passing the list to a method, the reference is sent. The only time it copies is if the implementation of the method copies it. The List constructor copies a list sent to it.

Line 32 should be

 days.Add(i, new List<int>(hours));

This copies the hours list to a new list and sends the new reference to the method.

avatar image Anxo · Feb 23, 2015 at 09:53 PM 0
Share

O$$anonymous$$G YES! You did it! Thank you for reading this really long question. This was driving my crazy b/c could not find the flaw.

Awesome $$anonymous$$, Thank you for your help.

avatar image
0

Answer by Radetic · Feb 24, 2015 at 03:45 AM

Isn't List a reference type? Therefore isn't the line

 days.Add (i, hours);

relating the same list to every day instead of giving each day it's own copy of the list?

Can't try right now in this computer, but my first test from your script would be changing that line to something like

 days.Add (i, new List<int>(hours));

just to be sure each day gets a separated copy

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0
Wiki

Answer by Alchemy_Fire · Feb 24, 2015 at 03:44 AM

C# object types are reference types. This means that you need to 'new up' an hours list each time you add it to a days dictionary - otherwise a reference will be shared between each element of the days dictionary and any change to one element will apply to all elements.

Something similar to the following is probably what you are after.

 foreach (string loc in locations)
 {
     var days = new Dictionary<int, List<int>>();
     for (int i = 0; i < 7; i++)
     {
         var hours = new List<int>();
         for (int j = 0; j < 24; j++)
             hours.Add(defaultPrice);
         days.Add(i, hours);
     }
 }


Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

22 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to send/copy array from dictionary to class and further to list of class 0 Answers

How to check if the string is on a text file 0 Answers

How do you create and control a proper turn manager? 0 Answers

Split Textasset into List 1 Answer

A node in a childnode? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges