I've some problems using the Dictionary. How can I get the value back from the Dictionary
I have stored some data in the Dictionary
Dictionary<UserSettings.Languages, string> objectiveLanguages
= new Dictionary<UserSettings.Languages, string>();
objectiveLanguages.Add(UserSettings.Languages.English, objectiveNameEnglish);
objectiveLanguages.Add(UserSettings.Languages.German, objectiveNameGerman);
Could someone explain me, how to retreive the stored value again?
Two options:
You know that the value will be present.
string str = objectiveLanguages[UserSettings.Languages.English];
return str;
You don't know that the value will be present, or you'd like to throw your own exception.
string str;
if(objectiveLanguages.TryGet(UserSettings.Languages.English, out str))
return str;
else
throw new ArgumentException(); // or return null, or whatever.
The choice between these depends on circumstances. Since you're dealing with an enum (or equivalent), the first should probably suffice. If the user was, say, entering data, on the other hand, I'd probably go with the second. It's a similar decision to that of using int.Parse versus int.TryParse.
Console.WriteLine("For key UserSettings.Languages.English, value = {0}.",
objectiveLanguages[UserSettings.Languages.English]);
/* returns the value of this key, if present.
*/
Ref the MSDN documentation here for more info.
Dictionary<UserSettings.Languages, string> objectiveLanguages
= new Dictionary<UserSettings.Languages, string>();
objectiveLanguages.Add(UserSettings.Languages.English, objectiveNameEnglish);
objectiveLanguages.Add(UserSettings.Languages.German, objectiveNameGerman);
// get some value out of the dict
string dictContent = objectiveLanguages[UserSettings.Languages.English];
Use square brackets with a key inside. For example:
// returns objectiveNameEnglish
var retrievedValue = objectiveLanguages[UserSettings.Languages.English];
For every pair you add, the first item is the key and the second item is the value mapped to it. MSDN has good examples https://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx
Related
I'm trying to print out a dictionary in C# that will simulate a graph. My dictionary looks like this:
Dictionary<int, List<int>> graph = new Dictionary<int, List<int>>();
In main, I add something to the dictionary, then try to print it out:
dicOfLists myDic = new dicOfLists();
myDic.AddEdge(1, 2);
myDic.printList();
The methods AddEdge and PrintList are pretty straightforward:
AddEdge:
public void AddEdge(int v1, int v2)
{
if (graph[v1] == null)
{
graph[v1] = new List<int> { v2 };
return;
}
graph[v1].Add(v2);
}
PrintList:
for (int i = 0; i < 1; i++)
{
Console.WriteLine(graph[i][i]);
}
I haven't done much programming in C# or Python, so dictionaries are new to me. I think why I'm getting tripped up is more conceptual than anything, specifically because I'm not sure how a list works within a dictionary.
The way I currently understand it is as follows:
Upon calling Addedge(1, 2) my dictionary is creating a list with a single element 2 at position 1 of my dictionary. This is because the first parameter represents the dictionary's key, and the second represents the list. The key functions like it would in a hashtable. When the key is provided, the dictionary looks at that position, and then creates a list.
Like I said, I'm new to C# so please don't skewer me too hard. While this might be something trivial like a straightforward syntax error, I'm not able to find much of anything for this specific problem online. Any help would be greatly appreciated!
You've got one method adding key/values to a dictionary and another printing them. The method printing them doesn't "know" what's been inserted, so it's better if that method doesn't make any assumptions about what's in the dictionary. Instead of just looping through a series of possible keys (0 to 1, 0 to n, etc.) it's better to operate according to what actually is in the dictionary.
var keys = graph.Keys;
// or, if you they were entered out of sequence and you want to sort them
var keys = graph.Keys.OrderBy(k => k);
// Now you're using the actual keys that are in the dictionary, so you'll never
// try to access a missing key.
foreach(var key in keys)
{
// It's not quite as clear to me what you're doing with these objects.
// Suppose you wanted to print out everything:
Console.WriteLine($"Key: {key}");
foreach(var value in graph[key])
{
Console.WriteLine(value);
}
}
I have Dictionary that the key is an array of int, and the value is a string. How can I get the value by check if int is contained in the key array?
public static Dictionary<int[], string> MyDic = new Dictionary<int[], string>
{
{new int[]{2,25},"firstValue"},
{new int[]{3,91,315,322},"secondValue"}
};
I have :
int number=91;
string value=?;
I need the value will get "secondValue"
I think this is a bad design choice. If the numbers don't repeat between keys (as you said in your comment for the question) then just flatten the keys into a simple Dictionary<int,string>. Just have the different integers all be keys for the same strings.
For example:
Dictionary<int,string>
{
[2] = "firstValue",
[25] = "firstValue",
};
In order to not repeat the same values but as different objects you can place a reference there:
string firstValue = "firstValue";
Dictionary<int,string>
{
[2] = firstValue,
[25] = firstValue,
};
In this case changing the value's content (not for a string as it is immutable but if it was some other object) for one key will change for all.
Use contains and a foreach loop (more readable than some other solutions):
string value;
int number = 91;
foreach(KeyValuePair<int[], string> entry in MyDic)
{
if (entry.Key.Contains(number))
{
value = entry.Value;
}
}
However, maybe a dictionary isn't the right choice for this.
Check out Gilads answer for another structure that you could use
string value = MyDic.FirstOrDefault(x => x.Key.Contains(number)).Value;
? is not needed, can not apply ? operand to KeyValuePair
something like
value = MyDic.FirstOrDefault(x => x.Key.Contains(number)).Value;
will return the first occurrence or null
Dictionary cannot have two values with same key. please tell which logic/algorithm being used in determining whether the key exists or not.
Eric Lippert explains this thouroughly in his blog post.
How about method ContainsKey of Dictionary?
There are many ways to check for the key but I think this method is most graceful.
Simple put it in try catch
if key exist will remain in try, else if not exists will come in catch
Dictionary<string, int> dic = new Dictionary<string, int>();
string str = "";
try
{
int a = dic["keytofind"];
str = "Key Found";
}
catch(Exception)
{
str = "Key Not Found";
}
Trie data structure is used to store the keys.
positive points of using this data structure :
1. Saving of storage space.
2. In O(Log(n)+constant) complexity can be determined about the existence of key.
More details about trie data structure can be found here
Dictionary<string, double> state = new Dictionary<string, double>(50);
state.Add("Alabama", 0.0570);
state.Add("Alaska", 0.1167);
state.Add("Arizona", 0.0592);
state.Add("Arkansas", 0.0835);
state.Add("California", 0.0739);
state.Add("Colorado", 0.0272);
state.Add("Connecticut", 0.06540);
state.Add("Delaware", 0.0825);
state.Add("Florida", 0.0503);
state.Add("Georgia", 0.0562);
state.Add("Hawaii", 0.0985);
state.Add("Idaho", 0.0736);
state.Add("Illinois", 0.0562);
state.Add("Indiana", 0.0648);
state.Add("Iowa", 0.0591);
state.Add("Kansas", 0.0654);
state.Add("Kentucky", 0.0734);
state.Add("Louisiana", 0.0685);
state.Add("Maine", 0.0770);
state.Add("Maryland", 0.0559);
state.Add("Massachusetts", 0.0630);
state.Add("Michigan", 0.0672);
state.Add("Minnesota", 0.0802);
state.Add("Mississippi", 0.0740);
state.Add("Missouri", 0.0517);
state.Add("Montana", 0.0708);
state.Add("Nebraska", 0.0610);
state.Add("Nevada", 0.0612);
state.Add("New Hampshire", 0.0387);
state.Add("New Jersey", 0.0661);
state.Add("New Mexico", 0.0826);
state.Add("New York", 0.0676);
state.Add("North Carolina", 0.0726);
state.Add("North Dakota", 0.0711);
state.Add("Ohio", 0.0609);
state.Add("Oklahoma", 0.0621);
state.Add("Oregon", 0.0576);
state.Add("Pennsylvania", 0.0617);
state.Add("Rhode Island", 0.0640);
state.Add("South Carolina", 0.0619);
state.Add("South Dakota", 0.0423);
state.Add("Tennessee", 0.0539);
state.Add("Texas", 0.0438);
state.Add("Utah", 0.0728);
state.Add("Vermont", 0.1060);
state.Add("Virginia", 0.0563);
state.Add("Washington", 0.0648);
state.Add("West Virginia", 0.0834);
state.Add("Wisconsin", 0.0693);
state.Add("Wyoming", 0.0778);
string stateKey = textBox1.Text.Trim().ToUpper();
if (state.ContainsKey(stateKey))
{
StateTax = state[stateKey];
}
else
{
string messageBoxText = "Missing rate for state " + stateKey;
MessageBox.Show(messageBoxText);
return;
}
So this is what i have so far, i cant get StateTax To take the value of one of my dictionary Values.This usually doesn't take me that long but my brain is just freezing lately on thinking. Whats the best way to write this?
You are upper casing:
string stateKey = textBox1.Text.Trim().ToUpper();
but dictionary keys are in proper caps:
"Wyoming"
Either place in dictionary as all lower or upper case, and do the same to your entered value, OR make entered text first caps (the former is preferable)
UPDATE: or even better! use Anthony's or Ed's idea of a case insensitive dictionary!
You're calling ToUpper on your key, but you didn't add the keys to the dictionary in all caps:
string stateKey = textBox1.Text.Trim().ToUpper();
"ALABAMA" != "Alabama", so you will need to either:
Call ToUpper() or ToLower() on your user input and enter your keys accordingly, or
Use a case insensitive compare <-- Better option
The Dictionary<K,V> class will take an IEqualityComparer<T> in one of its constructors. Use it to define how to compare key values.
var caseInsensitiveDictionary = new Dictionary<string, int>(
StringComparer.OrdinalIgnoreCase);
The StringComparer class implements the IEqualityComparer interface.
Your dictionary stores the keys like "Abc", but you are attempting to retrieve the value using the key "ABC". To fix your specific dilemna, specify a comparer that ignores case completely.
var stateTaxTable = new Dictionary<string, decimal>(StringComparer.CurrentCultureIgnoreCase);
Also notice I'm making the value a decimal as a suggestion. It is more fitting of storing a value to be used in a financial calculation. You would store it in the dictionary using the M suffix on the value. Example:
stateTaxTable.Add("Some State", 0.075M);
If you are multiplying a price by this value, you'd want the price to be a decimal, as well. Again, these are suggestions, but it's good to get in the habit of using the proper type for financial data.
The .ToUpper() is your problem.
Whatever's in the textbox is being normalized to uppercase, but the keys are case-sensitive.
Your are converting the state input to upper case. You will never find the entry in the dictionary.
Either (1) change code to use upper case state names or (2) remove the ToUpper and create the dictionary with a case insensitive comparer.
Or you can use
String stateKey =
CultureInfo.CurrentCulture.TextInfo.ToTitleCase(textbox1.Text);
What is the difference in Dictionary.add(key, value) and Dictionary[key] = value?
I've noticed that the last version does not throw an ArgumentException when inserting a duplicate key, but is there any reason to prefer the first version?
Edit: Does anyone have an authoritative source of information about this? I've tried MSDN, but it is as always a wild goose chase :(
The performance is almost a 100% identical. You can check this out by opening the class in Reflector.net
This is the This indexer:
public TValue this[TKey key]
{
get
{
int index = this.FindEntry(key);
if (index >= 0)
{
return this.entries[index].value;
}
ThrowHelper.ThrowKeyNotFoundException();
return default(TValue);
}
set
{
this.Insert(key, value, false);
}
}
And this is the Add method:
public void Add(TKey key, TValue value)
{
this.Insert(key, value, true);
}
I won't post the entire Insert method as it's rather long, however the method declaration is this:
private void Insert(TKey key, TValue value, bool add)
And further down in the function, this happens:
if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key))
{
if (add)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
}
Which checks if the key already exists, and if it does and the parameter add is true, it throws the exception.
So for all purposes and intents the performance is the same.
Like a few other mentions, it's all about whether you need the check, for attempts at adding the same key twice.
Sorry for the lengthy post, I hope it's okay.
The first version will add a new KeyValuePair to the dictionary, throwing if key is already in the dictionary. The second, using the indexer, will add a new pair if the key doesn't exist, but overwrite the value of the key if it already exists in the dictionary.
IDictionary<string, string> strings = new Dictionary<string, string>();
strings["foo"] = "bar"; //strings["foo"] == "bar"
strings["foo"] = string.Empty; //strings["foo"] == string.empty
strings.Add("foo", "bar"); //throws
To answer the question first we need to take a look at the purpose of a dictionary and underlying technology.
Dictionary is the list of KeyValuePair<Tkey, Tvalue> where each value is represented by its unique key. Let's say we have a list of your favorite foods. Each value (food name) is represented by its unique key (a position = how much you like this food).
Example code:
Dictionary<int, string> myDietFavorites = new Dictionary<int, string>()
{
{ 1, "Burger"},
{ 2, "Fries"},
{ 3, "Donuts"}
};
Let's say you want to stay healthy, you've changed your mind and you want to replace your favorite "Burger" with salad. Your list is still a list of your favorites, you won't change the nature of the list. Your favorite will remain number one on the list, only it's value will change. This is when you call this:
/*your key stays 1, you only replace the value assigned to this key
you alter existing record in your dictionary*/
myDietFavorites[1] = "Salad";
But don't forget you're the programmer, and from now on you finishes your sentences with ; you refuse to use emojis because they would throw compilation error and all list of favorites is 0 index based.
Your diet changed too! So you alter your list again:
/*you don't want to replace Salad, you want to add this new fancy 0
position to your list. It wasn't there before so you can either define it*/
myDietFavorites[0] = "Pizza";
/*or Add it*/
myDietFavorites.Add(0, "Pizza");
There are two possibilities with defining, you either want to give a new definition for something not existent before or you want to change definition which already exists.
Add method allows you to add a record but only under one condition: key for this definition may not exist in your dictionary.
Now we are going to look under the hood. When you are making a dictionary your compiler make a reservation for the bucket (spaces in memory to store your records). Bucket don't store keys in the way you define them. Each key is hashed before going to the bucket (defined by Microsoft), worth mention that value part stays unchanged.
I'll use the CRC32 hashing algorithm to simplify my example. When you defining:
myDietFavorites[0] = "Pizza";
What is going to the bucket is db2dc565 "Pizza" (simplified).
When you alter the value in with:
myDietFavorites[0] = "Spaghetti";
You hash your 0 which is again db2dc565 then you look up this value in your bucket to find if it's there. If it's there you simply rewrite the value assigned to the key. If it's not there you'll place your value in the bucket.
When you calling Add function on your dictionary like:
myDietFavorite.Add(0, "Chocolate");
You hash your 0 to compare it's value to ones in the bucket. You may place it in the bucket only if it's not there.
It's crucial to know how it works especially if you work with dictionaries of string or char type of key. It's case sensitive because of undergoing hashing. So for example "name" != "Name". Let's use our CRC32 to depict this.
Value for "name" is: e04112b1
Value for "Name" is: 1107fb5b
Dictionary.Add(key, value) and Dictionary[key] = value have different purposes:
Use the Add method to add new key/value pair, existing keys will not be replaced (an ArgumentException is thrown).
Use the indexer if you don't care whether the key already exists in the dictionary, in other words: add the key/value pair if the the key is not in the dictionary or replace the value for the specified key if the key is already in the dictionary.
Yes, that is the difference, the Add method throws an exception if the key already exists.
The reason to use the Add method is exactly this. If the dictionary is not supposed to contain the key already, you usually want the exception so that you are made aware of the problem.
To insert the Value into the Dictionary
Dictionary<string, string> dDS1 = new Dictionary<string, string>();//Declaration
dDS1.Add("VEqpt", "aaaa");//adding key and value into the dictionary
string Count = dDS1["VEqpt"];//assigning the value of dictionary key to Count variable
dDS1["VEqpt"] = Count + "bbbb";//assigning the value to key
Given the, most than probable similarities in performance, use whatever feel more correct and readable to the piece of code you're using.
I feel an operation that describes an addition, being the presence of the key already a really rare exception is best represented with the add. Semantically it makes more sense.
The dict[key] = value represents better a substitution. If I see that code I half expect the key to already be in the dictionary anyway.
One is assigning a value while the other is adding to the Dictionary a new Key and Value.