[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Dictionaries in C#

Posted on 2012-09-03
24
Medium Priority
?
730 Views
Last Modified: 2012-09-08
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

0
Comment
Question by:December2000
  • 8
  • 6
  • 5
  • +1
22 Comments
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 38360920
>>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
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 38360960
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
 
LVL 11

Expert Comment

by:MajorBigDeal
ID: 38361276
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 38361286
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
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 38361324
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
 
LVL 11

Expert Comment

by:MajorBigDeal
ID: 38361471
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
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 38361523
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
 
LVL 11

Expert Comment

by:MajorBigDeal
ID: 38361565
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
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 38361622
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
 

Author Comment

by:December2000
ID: 38361734
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
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 38361738
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
 

Author Comment

by:December2000
ID: 38361741
yes @kaufmed
0
 
LVL 11

Accepted Solution

by:
MajorBigDeal earned 2000 total points
ID: 38361766
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
 

Author Closing Comment

by:December2000
ID: 38361792
Thank you
0
 
LVL 11

Expert Comment

by:MajorBigDeal
ID: 38361797
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
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 38362415
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
 

Author Comment

by:December2000
ID: 38364305
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
 
LVL 11

Expert Comment

by:MajorBigDeal
ID: 38365462
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
 

Author Comment

by:December2000
ID: 38369180
I am a "she" :)
0
 
LVL 11

Expert Comment

by:MajorBigDeal
ID: 38370106
@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
 

Author Comment

by:December2000
ID: 38370639
No Problem!
0
 
LVL 11

Expert Comment

by:MajorBigDeal
ID: 38379912
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

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

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.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Article by: evilrix
Looking for a way to avoid searching through large data sets for data that doesn't exist? A Bloom Filter might be what you need. This data structure is a probabilistic filter that allows you to avoid unnecessary searches when you know the data defin…
This video teaches viewers about errors in exception handling.
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.
Suggested Courses
Course of the Month18 days, 17 hours left to enroll

834 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question