Handle Collision using Hashtable Class in c# - c#

In the below scenario how can I handle or implement collision in C# using the Hashtable class? If the 'Key' value is same I am getting an "Argument Exception".
static void Main(string[] args)
{
Console.Write("Enter a string:");
string input = Console.ReadLine();
checkString(input);
Console.ReadLine();
}
static void checkString(string input)
{
Hashtable hashTbl = new Hashtable();
foreach(char c in input)
{
hashTbl.Add(c.GetHashCode(), c);
}
printHash(hashTbl);
}
static void printHash(Hashtable hash)
{
foreach(int key in hash.Keys)
{
Console.WriteLine("Key: {0} Value: {1}",key,hash[key]);
}
}
My Expectation:
What do I need to do in the 'Value' argument to get around the 'Collision' issue. I am trying to check if the string consists of unique characters.

It seems you are misunderstanding how the Hashtable class works (and it has been deprecated since 2005 - use Dictionary<K,V> instead, but its behavior here is identical).
It seems you're expecting it to be your job to get an object's hashcode and add it to the hashtable. It isn't. All you need to do is add the object you want to use as key (each character), and the internal implementation will extract the hashcode.
However, what you're actually doing won't work even if you added the key object yourself. You're taking an input string (say, "test"), and for each character, you're adding it to the hashtable as a key. But since keys are, by definition, unique, you'll be adding the character 't' twice (it shows up twice in the input), so you'll get an exception.

I am trying to check if the string consists of unique characters.
Then you need keys only without values, that's what HashSet<T> is for.
var chars = new HashSet<char>();
foreach (char c in input)
{
if (chars.Contains(c))
{
// c is not unique
}
else
{
chars.Add(c);
}
}
But I'd prefer usin LINQ in this case:
var hasUniqueChars = input.Length == input.Distinct().Count();

As previously stated you should probably switch to the Dictionary<TKey, TValue> class for this.
If you want to get around the collission issue, then you have to check the key for existence.
Dictionary<string, object> dictValues = new Dictionary<string, object>();
Then you can use check for collission:
if (dictValues.ContainsKey(YourKey))
{
/* ... your collission handling here ... */
}
else
{
// No collission
}
Another possibility would be, if you are not interested in preserving previous values for the same key:
dictValues[YourKey] = YourValue;
This will add the key entry if it is not there already. If it is, it will overwrite its value with the given input.

Related

Dictionary Unhandled Exception in C#: "The given key was not present in the dictionary"

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);
}
}

Replace a Specific Text From a Text

I'm writing a chat helper tool for a game with a custom library.
I want to change specific variables when player sends the message.
This is my code
static List<string> asciis = new List<string> { "shrug", "omg" };
static List<string> converteds = new List<string> { #"¯\_(ツ)_/¯", #"◕_◕"};
private static void Game_OnInput(GameInputEventArgs args)
{
newtext = args.Input;
foreach (var ascii in asciis)
{
foreach (var converted in converteds)
{
if (args.Input.Contains(ascii))
{
newtext = args.Input.Replace(ascii, converted);
Game.Say(newtext);
}
}
}
}
As you can see I'm trying to get the texts from "asciis" and convert them to "converteds" (in order).
Whenever I type something that not in "asciis" list it perfectly works. But whenever I type shrug it prints ¯\_(ツ)_/¯ + ◕_◕ + ◕_◕ (it prints omg 2 times). Same in omg too.
You probably understand that I'm really beginner. I really didn't understand what is wrong with this code...
It seems that your two lists have the same length (in terms of elements contained) and each element in one list has its replacement in the same position in the other list.
Then you could treat the two lists as two arrays and use a different way to search for the input term and replace it with the substitution text
private static void Game_OnInput(GameInputEventArgs args)
{
newtext = args.Input;
for(int x = 0; x < ascii.Count; x++)
if (args.Input.Contains(ascii[x]))
{
newtext = args.Input.Replace(ascii[x], converted[x]);
Game.Say(newtext);
}
}
While i don't think there is a big improvement, you could also implement the same with a dictionary
static Dictionary<string, string> converter = new Dictionary<string, string>()
{
{"shrug", #"¯\_(ツ)_/¯"},
{"omg", #"◕_◕"}
};
private static void Game_OnInput(GameInputEventArgs args)
{
newtext = args.Input;
foreach(KeyValuePair<string, string> kvp in converter)
if (args.Input.Contains(kvp.Key))
{
newtext = args.Input.Replace(kvp.Key, kvp.Value);
Game.Say(newtext);
}
}
Well, probably is a bit more readable, but still we need traversing the dictionary Keys one by one.
As Daniel pointed out in his comment, this is a good use case for dictionaries.
Have a dictionary that maps the text you want replaced to the stuff you want to be replaced with:
Dictionary<string, string> dict = new Dictionary<string, string>
{
{"shrug", #"¯\_(ツ)_/¯" },
{"omg", "◕_◕" }
}; // etc
Then find all occurrences of the keys from the dictionary and replace them with the corresponding values.
Also why are you using static methods and fields? I may be wrong, but I expect most, if not all of your other methods and fields are static as well. I strongly recommend avoiding getting used to them. Try learning more about OOP instead.
Your main problem is that you are always replacing on args.Input, but storing the results in newtext each time, overwriting your previous replacements. Your next problem is that you are outputting the result after each replacement attempt so that's why you are getting multiple weird output results.
I also suggest a dictionary since by definition, it is a mapping of one thing to another. Also, note my changes below, I have moved the Game.Say call outside of the loops and changed "args.Input.Replace" to "newtext.Replace"
Dictionary<string, string> dictionary = new Dictionary<string, string>
{
{"shrug", #"¯\_(ツ)_/¯" },
{"omg", "◕_◕" }
};
private static void Game_OnInput(GameInputEventArgs args)
{
string newtext = args.Input;
foreach(string key in dictionary.Keys){
newtext = newtext.Replace(key,dictionary[key]);
}
Game.Say(newtext);
}

Dictionary object performance

I have a possible implementation scenario where I need a dictionary object that will take 3 variables. A dialect, a query name and a query string. I should note at this stage that writing a separate class object is not an option.
My question is which of the following would perform better.
A) A single dictionary object that takes the first two variables in as a composite key e.g. "dialect,queryname" and the 3rd variable as the value.
private Dictionary<string, string>
B) A dictionary object that has another dictionary object as the value so the first variable would be the key of the primary dictionary object, the 2nd variable would be the key of the 2nd dictionary object and finally the 3rd variable would be the value of the second dictionary object.
private Dictionary<string, Dictionary<string, string>>
Seems obvious but the compiler is a mysterious thing so thought I should ask you guys.
Thanks
Just mucking around for my own amusement ..
Dictionary<string, string> md1 = new Dictionary<string,string>();
Dictionary<string, Dictionary<string, string>> md2 = new Dictionary<string, Dictionary<string, string>>();
Stopwatch st = new Stopwatch();
st.Start();
for (int i = 0; i < 2000000; i++)
{
md1.Add(i.ToString(), "blabla");
}
st.Stop();
Console.WriteLine(st.ElapsedMilliseconds);
st.Reset();
st.Start();
for (int i = 0; i < 2000000; i++)
{
md2.Add(i.ToString(), new Dictionary<string, string>());
}
st.Stop();
Console.WriteLine(st.ElapsedMilliseconds);
Console.ReadLine();
output:
831
1399
As long as you're sure that the key "dialect,queryname" is unique, I think the first solution is faster. In the second one, you'd have to do one more dictionary lookup, which is probably more costly than a string concatenation.
Why don't you use:
Dictionary<string, KeyValuePair<string, string>>
I think is better than both.
This is not a matter of performance, as the two have completely different semantics.
The first gives you a way to use one object to find another object.
The second gives you a way to use one object to find another object, in which you can use yet another object to find a third object.
There is slightly different functionality in terms of how these can be later extended.
Most generally, I'd use Dictionary<Tuple<string, string>, string>. This would give me a composite key that is clearly a composite key.
Actually, that's not true, I'd create a new class. How is that not an option? Still, if it was homework and "do not create a new class" was part of the question, I'd use Dictionary<Tuple<string, string>, string>.
Edit:
class DialectQuery : IEquatable<DialectQuery>
{
public Dialect{get;private set}
public Name{get;private set;}
public DialectQuery(string dialect, string name)
{
Dialect = dialect;
Name = name;
}
public bool Equals(DialectQuery other)
{
return other != null && Name == other.Name && Dialect == other.Dialect;
}
public override bool Equals(object other)
{
return Equals((object)other);
}
public override int GetHashCode()
{
int dHash = Dialect.GetHashCode();
return (dHash << 16 | dHash >> 16) ^ Name.GetHashCode();
}
}
So far it behaves exactly the same as Tuple. Now though if I get a change request that dialects must be case-insensitive but query names case-sensitive, or that dialects are codes and therefore require invariant comparison but names are human-input and therefore require culture-aware comparison, or anything else, I've got two simple changes to make.
YAGNI doesn't apply, it's not coding a massive object "in case you need it", it's defining a good "okay, I probably don't need it, but if I do it'll go here" point.

How to use custom IComparer for SortedDictionary?

I am having difficulties to use my custom IComparer for my SortedDictionary<>. The goal is to put email addresses in a specific format (firstnam.lastname#domain.com) as the key, and sort by last name.
When I do something like this:
public class Program
{
public static void Main(string[] args)
{
SortedDictionary<string, string> list = new SortedDictionary<string, string>(new SortEmailComparer());
list.Add("a.johansson#domain.com", "value1");
list.Add("b.johansson#domain.com", "value2");
foreach (KeyValuePair<string, string> kvp in list)
{
Console.WriteLine(kvp.Key);
}
Console.ReadLine();
}
}
public class SortEmailComparer : IComparer<string>
{
public int Compare(string x, string y)
{
Regex regex = new Regex("\\b\\w*#\\b",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
string xLastname = regex.Match(x).ToString().Trim('#');
string yLastname = regex.Match(y).ToString().Trim('#');
return xLastname.CompareTo(yLastname);
}
}
I get this ArgumentException:
An entry with the same key already exists. when adding the second item.
I haven't worked with a custom IComparer for a SortedDictionary before, and I fail to see my error , what am I doing wrong?
If the 2 lastNames are equal then compare for example the whole email like:
int comp = xLastname.CompareTo(yLastname);
if (comp == 0)
return x.CompareTo(y);
return comp;
Actually, sorteddictionary comparison is also used to distinguish amongst keys* , so you must specify a complete comparison (not only your sorting strategy)
EDIT:
* I mean in sortedDictionary 2 keys are equal if Comparer gives 0
Well, I haven't taken apart your comparer - but it looks like it's just comparing by last name, and you're trying to add the same last name (johansson) twice. That should give you an ArgumentException.
What did you want to happen - and what do you want your comparer to do?
Perhaps you want to sort by last name and then first name? That way you can have two email addresses with the same last name but different first names, and have them still be in the dictionary together, ordered by first name.

Different ways of adding to Dictionary

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.

Categories

Resources