Dictionaries in C#

I am a newbie and learning new concepts in C#.  Another expert was cool enough to introduce me to dictionaries. However, I am Sort of lost as to where I place the loop with a dictionary...  Meaning every account should be able to loop until all the deposits are complete and the accounts are totaled at the end.  Right now I can only enter one "deposit" per account.

    class Program
    {
        static void Main(string[] args)
        {

            // cretae a dictionary where key is a account name and value - account amount
            // amout is initially zero
            Dictionary<string, double> accounts = new Dictionary<string, double>();
            accounts.Add("A", 0);
            accounts.Add("B", 0);
            accounts.Add("C", 0);

            // checked what we have
            foreach (KeyValuePair<string, double> item in accounts)
            {
               Console.WriteLine("Account {0}, amount = {1}", item.Key, item.Value);
            }
            // enter new amounts:
            // We cannot modify the dictionary in foreach loop
            // Therefore copy keys to a list:
            List<string> accountNames = new List<string>(accounts.Keys);
            foreach(string accountName in accountNames)
            {

                Console.WriteLine(" Please enter new amount for the Account {0}", accountName);
                accounts[accountName] = Convert.ToDouble(Console.ReadLine());
            }

            // check again
            foreach (KeyValuePair<string, double> item in accounts)
            {
                Console.WriteLine("Account {0}, amount = {1}", item.Key, item.Value);
            }
            Console.ReadLine();

        }
    }

Open in new window

December2000Asked:
Who is Participating?
 
MajorBigDealConnect With a Mentor Commented:
For stopping using a "Z" instead of an empty line (I hope that is what you meant), one way would be to change the loop to look like this:

foreach (string accountName in accountNames)
            {
                string line;                
                while (true)
                {
                    Console.WriteLine(" Please enter new amount for the Account {0} ", accountName);
                    line = Console.ReadLine();
                    if (line.StartsWith("Z", StringComparison.CurrentCultureIgnoreCase)) break;                                        
                    Double amount = Convert.ToDouble(line);
                    KeyValuePair<string,double> deposit = new KeyValuePair<string,double>(accountName,amount);
                    deposits.Add(deposit);
                }
            }
0
 
AndyAinscowFreelance programmer / ConsultantCommented:
>>Right now I can only enter one "deposit" per account.

Yes - that is how a dictionary works.  It has one item (deposit) per key value.

I think you really want something a little more complex.  eg.  Each dictionary entry should be a list, so one key is linked to a list (which can have many entries).


Dictionary<string, List<Double>> accounts = new Dictionary<string, List<Double>>();
0
 
käµfm³d 👽Commented:
There is also a Lookup class which is similar to a Dictionary, but instead of unique keys, the keys can repeat. I haven't used the class myself, so I can't really offer any insight into its usage. Myself, I would take the approach AndyAinscow mentions.
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
MajorBigDealCommented:
I think this is a good approach, although it just uses List rather than Dictionary.  

When you are done entering the deposits for an account you just press enter without a value to move on to the next account.

 static void Main(string[] args)
        {
            // create a list of accounts
            List<string> accountNames = new List<string>();
            accountNames.Add("A");
            accountNames.Add("B");
            accountNames.Add("C");                                  

            // create a list of deposits          
            List<KeyValuePair<string, double>> deposits = new List<KeyValuePair<string, double>>();            
            foreach (string accountName in accountNames)
            {
                string line;
                do
                {
                    Console.WriteLine(" Please enter new amount for the Account {0} ", accountName);
                    line = Console.ReadLine();
                    if (line.Length > 0)
                    {
                        Double amount = Convert.ToDouble(line);
                        KeyValuePair<string,double> deposit = new KeyValuePair<string,double>(accountName,amount);
                        deposits.Add(deposit);
                    }
                } while (line.Length > 0);
            }

            // Display deposits
            foreach (KeyValuePair<string, double> item in deposits)
            {
                Console.WriteLine("Account {0}, amount = {1}", item.Key, item.Value);
            }            
            Console.ReadLine();
        }
0
 
käµfm³d 👽Commented:
And just how is a List<KeyValuePair> different than a Dictionary--that is, outside of the lack of a hash function for quick lookups?
0
 
AndyAinscowFreelance programmer / ConsultantCommented:
Basically a rewording of the previous comment by kaufmed.

A dictionary should give VERY rapid lookups of the key.  Using a list to store the keys should result in worse lookup performance when compared to a dictionary.  With say 10,000 accounts a dictionary might just need 3 or 4 hashes to find the key, the list could take 9,999
0
 
MajorBigDealCommented:
Not a rewording, it is a big difference.  The previous suggestion was to overcome the Dictionary requirement of unique keys by either using a Lookup class or by storing Lists inside Dictionary elements.  

My suggestion is that a single List (without the Dictionary) is more appropriate for the problem at hand.  

Cmon guys, concentrate on helping the Asker not on denigrating someone else;'s comments.
0
 
käµfm³d 👽Commented:
My suggestion is that a single List (without the Dictionary) is more appropriate for the problem at hand.
And I respectfully disagree. You've changed access of the items from O(1) to O(n)--in other words, you made looking up items much slower. For smaller lists, this is probably of little consequence; for larger lists, the difference would be notable.

P.S.

Feel free to denigrate any of my answers if you think they are incorrect. I'm here to learn too  = )
0
 
MajorBigDealCommented:
It isn't the size of the list that is the determining factor it is the question of Random access or not.  

There is nothing is the problem description about random access. In fact, quite the opposite, it seems to be specifically about sequentially processing the accounts.  In that case, with a large list, processed sequentially, the List will be more efficient than the Dictionary.  

To address your answer,  I don't think that a discussion of big O notation, and the limiting behavior of functions is a big help in this question. Maybe what you should do is to post some example code that does what the December2000 is trying to accomplish but using a Dictionary or Lookup.

The "denigrating" comment was in regard to say that my answer was a "rewording", which it certainly was not.

What happens when experts start to snipe at each other's answers instead of focusing on helping the Asker, is exactly what is happening here.  The question becomes a debate  between various experts instead of focusing on helping the person who is looking for help.
0
 
käµfm³d 👽Commented:
I think you are making assumptions about the environment in question (as surely as am I). Sure, this particular request deals with processing the data in a sequential fashion. Can you, not being the owner of the problem, safely say that that encompasses the entire problem domain? The Dictionary must have been used for a reason. If the Dictionary is not required for the asker's environment, then I concede that a change in the structure of the code could very well be the solution.

To address your answer,  I don't think that a discussion of big O notation, and the limiting behavior of functions is a big help in this question.
I'm not sure how one sentence entails a "discussion," but I'll take your word for it. My use of "big-O" was just technical parlance; you'll notice I immediately followed it with "layman" terminology:

in other words, you made looking up items much slower


The "denigrating" comment was in regard to say that my answer was a "rewording", which it certainly was not.
Perhaps I misread the comment, but I took AndyAinscow's comment to mean that his comment was a rewording of my comment.

What happens when experts start to snipe at each other's answers instead of focusing on helping the Asker, is exactly what is happening here.
I'm sorry you feel that sniping is going on here. I suppose that's one of the detriments of being on a site which turns providing answers into a competition. You proposed a solution; I stated why I thought it wasn't the right one; it's on you to state why I am "full of beans."

Defend your position; don't get defensive  = )
0
 
December2000Author Commented:
Well, the good news is I am learning a lot about the use of lists and dictionaries in the C# environment  :0) I appreciate the answers and the exchange! I think it is cool to be passionate about your craft and I am working to the end. @majorbigdeal I appreciate you posting the code because as a newbie as you know learning a new language is tough. I can tell that all of you are seasoned developers. With that said I have been playing with code above and it works but, it is not totaling up each account. So, with that said.... what would I change to give a total of each account upon exit and change  it to use 'Z'  to exit. If not that is cool because I am learning so much and the journey is where you learn. Hopefully one day I can be a guru and help newbies too! Thanks to each of you.
0
 
käµfm³d 👽Commented:
With that said I have been playing with code above and it works
When you say "code above," are you referring to MajorBigDeal's code?
0
 
December2000Author Commented:
yes @kaufmed
0
 
December2000Author Commented:
Thank you
0
 
MajorBigDealCommented:
For summing the totals, I would suggesting using (ahem) a Dictionary.   Not because it is more efficient but because it is easier.

It doesn't really matter unless you are processing a large number of deposits but another expert might be interested in consolidating and making this more efficient.  

 static void Main(string[] args)
        {          
            List<string> accountNames = new List<string>();
            accountNames.Add("A");
            accountNames.Add("B");
            accountNames.Add("C");                                  

            // create a list of deposits          
            List<KeyValuePair<string, double>> deposits = new List<KeyValuePair<string, double>>();            
            foreach (string accountName in accountNames)
            {
                string line;                
                while (true)
                {
                    Console.WriteLine(" Please enter new amount for the Account {0} ", accountName);
                    line = Console.ReadLine();
                    if (line.StartsWith("Z", StringComparison.CurrentCultureIgnoreCase)) break;                                        
                    Double amount = Convert.ToDouble(line);
                    KeyValuePair<string,double> deposit = new KeyValuePair<string,double>(accountName,amount);
                    deposits.Add(deposit);
                }
            }

            Dictionary<string, double> totals = new Dictionary<string, double>();
            foreach (KeyValuePair<string, double> item in deposits)
            {
                if (totals.ContainsKey(item.Key))
                {
                    totals[item.Key] += item.Value;                
                }
                else
                {
                    totals.Add(item.Key,item.Value);                
                }
            }
            foreach (KeyValuePair<String, double> total in totals)
            {
                Console.WriteLine("Account {0}, amount = {1}", total.Key, total.Value);
            }
            Console.ReadLine();
        }
    }
0
 
AndyAinscowFreelance programmer / ConsultantCommented:
Wierd.
Don't use a dictionary, my code with a list is better.
Then later - actually a dictionary would be better after all.

ps.  I've asked a moderator to review concerning some of the comments of a more personal nature.
0
 
December2000Author Commented:
Thank all of you! Excellent @ MajorBigDeal... It works :) I am going to study this code and implement it... I have learned a really cool technique in a few days...
0
 
MajorBigDealCommented:
You are welcome December2000, I'm glad that you were helped as that was the goal.  I hope you have an improved understanding of when it is more appropriate to use a List versus a Dictionary.  In the case of your problem, I thought that a List was more appropriate for storing deposits as there was not a unique key readily available. That is not to say that using a Dictionary is wrong, it was just not my first choice. OTOH, for calculating totals I felt that the Dictionary was the perfect choice since a unique key was naturally available.  A list would have worked here as well, but again, it was not my first choice. The right tool for the right job.
0
 
December2000Author Commented:
I am a "she" :)
0
 
MajorBigDealCommented:
@December2000, sorry about that.  I'm an old man and I still get caught in my sexist assumptions.   When I started programming in the 70's there were very few women programmers.
0
 
December2000Author Commented:
No Problem!
0
 
MajorBigDealCommented:
If you are going to remove those comments then you should also remove Andy's comment at #a38362415.  

It is a misrepresentation for several reasons. I was not the one who started with the "my answer is better" nonsense.   Also, it summarizes my contribution in an insulting manner.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.