How to convert Dictionary<> to Hashtable in C#? - c#

I see many question/answers about how to convert a Hashtable to a Dictionary, but how can I convert a Dictionary to a Hashtable?

The easiest way is using constructor of Hashtable:
var dictionary = new Dictionary<object, object>();
//... fill the dictionary
var hashtable = new Hashtable(dictionary);

Dictionary<int, string> dictionary = new Dictionary<int, string>
{
{1,"One"},
{2,"Two"}
};
Hashtable hashtable = new Hashtable(dictionary);
Try this

Seems pretty rare to want to do, but at the simplest:
var hash = new Hashtable();
foreach(var pair in dictionary) {
hash.Add(pair.Key,pair.Value);
}
(assuming no unusual "implements typed equality check but not untyped equality check" etc)

You might want to consider using the Hashtable constructor overload that takes an IEqualityComparer parameter:
var hashtable = new Hashtable(dictionary, (IEqualityComparer) dictionary.Comparer);
In this way, your Hashtable uses the same Comparer as the dictionary. For example, if your dictionary used a case-insensitive string key, you might want your Hashtable to be case-insensitive too. E.g.:
var d = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
d.Add("a", "a");
d.Add("b", "b");
bool found;
found = d.ContainsKey("A"); // true
var hashtable1 = new Hashtable(d);
var hashtable2 = new Hashtable(d, (IEqualityComparer) d.Comparer);
found = hashtable1["A"] != null; // false - by default it's case-sensitive
found = hashtable2["A"] != null; // true - uses same comparer as the original dictionary

Related

How to pass Dictionary TKey and TValue to a method one by one in C#

I have a Dictionary in code as:
SqlCommand query = con.CreateCommand();
query.CommandText = #"select pid, p_title from sub_aminer_paper where pid IN (/*a long list of Pid's*/)";
SqlDataReader reader = query.ExecuteReader();
Dictionary<int, string> paper_title = new Dictionary<int, string>();
paper_title.Add(Convert.ToInt32(reader["pid"]), reader["p_title"].ToString() );
And string lines reading a text file as:
var lines = System.IO.File.ReadLines(#"D:\~\research_fields.txt");
I want to pass Dictionary TKey and TValue to a method to be called in a HashSet as:
var similarity = new HashSet<Tuple<string, double, int>>();
similarity.Add(lines.Select(line => Tuple.Create(line, p.calculate_CS(line, paper_title.Select(item => item.Value).ToString()), paper_title.Select(item => item.Key))));
But this line of code giving error of some invalid arguments.
The method p.calculate_CS(string, string) takes two arguments of type string. I have to take one string from lines and one string from Dictionary i.e. paper_title. The third argument for Tuple is of type int that will be the Key from Dictionary.
Please help in this regard. Thanks!
From the discussion in comments, I think your code should look something like
var similarity = new HashSet<Tuple<string, double, int>>();
foreach(var key in paper_title.Keys){
similarity.Add(lines.Select(line => Tuple.Create(line,
p.calculate_CS(line, paper_title[key]), key)));
}
This code will iterate through each key in your dictionary and will call calculate_CS method with appropriate attributes.
The TKey and TValue can be passed one by one to method using following:
Dictionary<int, string> paper_title = new Dictionary<int, string>();
paper_title.Add(Convert.ToInt32(reader["pid"]), reader["p_title"].ToString() );
var similarity = new HashSet<Tuple<string, double, int>>();
foreach(KeyValuePair<int, string> item in paper_title)
{
similarity.UnionWith(lines.Select(line => Tuple.Create(line, p.calculate_CS(line, item.Value), item.Key)));
}

Finding already existing value in Key Value pair

I am storing a string and int value in Key value pair.
var list = new List<KeyValuePair<string, int>>();
While adding i need to check if string(Key) already exists in list, if exists i need to add it to Value instead of adding new key.
How to check and add?
Instead of List you can use Dictionary and check if it contains key then add the new value to the existing key
int newValue = 10;
Dictionary<string, int> dictionary = new Dictionary<string, int>();
if (dictionary.ContainsKey("key"))
dictionary["key"] = dictionary["key"] + newValue;
use dictonary. Dictionary in C# and I suggest you to read this post Dictonary in .net
Dictionary<string, int> dictionary =
new Dictionary<string, int>();
dictionary.Add("cat", 2);
dictionary.Add("dog", 1);
dictionary.Add("llama", 0);
dictionary.Add("iguana", -1);
to check. use ContainsKey ContainsKey
if (dictionary.ContainsKey("key"))
    dictionary["key"] = dictionary["key"] + yourValue;
If you need use the list,you must foreach the list,and look for the keys.
Simplely,you can use hashtable.
For anyone who has to use a List (which was the case for me, since it does things Dictionary doesn't), you can just use a lambda expression to see if the List contains the Key:
list.Any(l => l.Key == checkForKey);
Your needs exactly describe the design of Dictionarys?
Dictionary<string, string> openWith =
new Dictionary<string, string>();
// Add some elements to the dictionary. There are no
// duplicate keys, but some of the values are duplicates.
openWith.Add("txt", "notepad.exe");
// If a key does not exist, setting the indexer for that key
// adds a new key/value pair.
openWith["doc"] = "winword.exe";
For sure, dictionary is preferable in your case. You can not modify the Value of KeyValue<string,int> class as it is Immutable.
But even if you still want to use List<KeyValuePair<string, int>>();. You can use IEqualityComparer<KeyValuePair<string, int>>. Code will be like.
public class KeyComparer : IEqualityComparer<KeyValuePair<string, int>>
{
public bool Equals(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
{
return x.Key.Equals(y.Key);
}
public int GetHashCode(KeyValuePair<string, int> obj)
{
return obj.Key.GetHashCode();
}
}
And use it in Contains like
var list = new List<KeyValuePair<string, int>>();
string checkKey = "my string";
if (list.Contains(new KeyValuePair<string, int>(checkKey, int.MinValue), new KeyComparer()))
{
KeyValuePair<string, int> item = list.Find((lItem) => lItem.Key.Equals(checkKey));
list.Remove(item);
list.Add(new KeyValuePair<string, int>("checkKey", int.MinValue));// add new value
}
which does not sounds good way.
hope this info helps..

Case insensitive access for generic dictionary

I have an application that use managed dlls. One of those dlls return a generic dictionary:
Dictionary<string, int> MyDictionary;
The dictionary contains keys with upper and lower case.
On another side I am getting a list of potential keys (string) however I cannot guarantee the case. I am trying to get the value in the dictionary using the keys. But of course the following will fail since I have a case mismatch:
bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );
I was hoping the TryGetValue would have an ignore case flag like mentioned in the MSDN doc, but it seems this is not valid for generic dictionaries.
Is there a way to get the value of that dictionary ignoring the key case?
Is there a better workaround than creating a new copy of the dictionary with the proper StringComparer.OrdinalIgnoreCase parameter?
There's no way to specify a StringComparer at the point where you try to get a value. If you think about it, "foo".GetHashCode() and "FOO".GetHashCode() are totally different so there's no reasonable way you could implement a case-insensitive get on a case-sensitive hash map.
You can, however, create a case-insensitive dictionary in the first place using:-
var comparer = StringComparer.OrdinalIgnoreCase;
var caseInsensitiveDictionary = new Dictionary<string, int>(comparer);
Or create a new case-insensitive dictionary with the contents of an existing case-sensitive dictionary (if you're sure there are no case collisions):-
var oldDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var newDictionary = new Dictionary<string, int>(oldDictionary, comparer);
This new dictionary then uses the GetHashCode() implementation on StringComparer.OrdinalIgnoreCase so comparer.GetHashCode("foo") and comparer.GetHashcode("FOO") give you the same value.
Alternately, if there are only a few elements in the dictionary, and/or you only need to lookup once or twice, you can treat the original dictionary as an IEnumerable<KeyValuePair<TKey, TValue>> and just iterate over it:-
var myKey = ...;
var myDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var value = myDictionary.FirstOrDefault(x => String.Equals(x.Key, myKey, comparer)).Value;
Or if you prefer, without the LINQ:-
var myKey = ...;
var myDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
int? value;
foreach (var element in myDictionary)
{
if (String.Equals(element.Key, myKey, comparer))
{
value = element.Value;
break;
}
}
This saves you the cost of creating a new data structure, but in return the cost of a lookup is O(n) instead of O(1).
For you LINQers out there that never use a regular dictionary constructor
myCollection.ToDictionary(x => x.PartNumber, x => x.PartDescription, StringComparer.OrdinalIgnoreCase)
There is much simpler way:
using System;
using System.Collections.Generic;
....
var caseInsensitiveDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
Its not very elegant but in case you cant change the creation of dictionary, and all you need is a dirty hack, how about this:
var item = MyDictionary.Where(x => x.Key.ToLower() == MyIndex.ToLower()).FirstOrDefault();
if (item != null)
{
TheValue = item.Value;
}

How to convert NameValueCollection to Hashtable

I have a NameValueCollection object and I need to convert it to a Hashtable object, preferrably in one line of code. How can I achieve this?
You should consider using a generic Dictionary instead since it's strongly-typed, whereas a Hashtable isn't. Try this:
NameValueCollection col = new NameValueCollection();
col.Add("red", "rouge");
col.Add("green", "verde");
col.Add("blue", "azul");
var dict = col.AllKeys
.ToDictionary(k => k, k => col[k]);
EDIT: Based on your comment, to get a HashTable you could still use the above approach and add one more line. You could always make this work in one line but 2 lines are more readable.
Hashtable hashTable = new Hashtable(dict);
Alternately, the pre-.NET 3.5 approach using a loop would be:
Hashtable hashTable = new Hashtable();
foreach (string key in col)
{
hashTable.Add(key, col[key]);
}
It takes more than one line but it's decently simple
NameValueCollection nv = new NameValueCollection();
Hashtable hashTable = new Hashtable();
nv.Add("test", "test");
foreach (string key in nv.Keys)
{
hashTable.Add(key, nv[key]);
}
It compiles and executes as expected.

How to convert a sortedDictionary into Dictionary?

Dictionary<string, string> optionDictionary = new Dictionary<string, string>();
optionDictionary = ....;
SortedDictionary<string, string> optionsSorted;
if(sorting)
{
optionsSorted = new SortedDictionary<string, string>(optionDictionary );
// Convert SortedDictionary into Dictionary
}
return optionDictionary ;
You can pass in your optionsSorted<TKey,TValue> dictionary as a parameter to an instance of a new Dictionary<TKey,TValue>, Like so:
var dictionary = new Dictionary<type1,type2>(optionsSorted);
Try the following
var dictionary = optionsSorted.ToDictionary(x => x.Key, x=> x.Value);
It is not entirely clear to me what you are trying to accomplish. I am assuming that you have a function that returns a Dictionary and you want it to be a sorted dictionary when sorting is true.
If that is true, then you need a return type that can be a Dictionary or a SortedDictionary.
If you want a single function doing that, I would use IDictionay as return type of the method.
Just use the ToDictionary method.

Categories