unsort Hashtable - c#

i am writing a program in C#
i have a code like this
Hashtable ht = new Hashtable();
ht.Add("1", "One");
ht.Add("2", "Two");
ht.Add("3", "Three");
ht.Add("4", "Four");
but Compiler sort it
i wanna know how can i prevent sorting hashtable
please help me

A HashTable doesn't do sorting as such. It does rearrange the items based on their hash code, so the original order isn't preserved.
If you want to preserve the original order, or want to specify a sort order, you can't use a HashTable only.
To specify a different sort order, you can use a SortedDictionary<T>. To preserve the original order, you can add the items both to a Dictionary<T> and a List<T>.

What do you mean by the compiler sorting it? There is definitely NO sorting done. How are you looping over the items?
I think that order of items when you loop over the keys isn't guaranteed ->
foreach(object key in hashtable.Keys){
...
}
but from your question I think you'd like to retrieve the items in the exact same order as you have inserted them - maybe the best solution would be to keep parallel List of your keys; and retrieve keys for looping over hashtable from there.

Use a Dictionary<int, string> or Dictionary <string, string> instead.

When doing:
Hashtable ht = new Hashtable();
ht.Add("1", "One");
ht.Add("2", "Two");
ht.Add("3", "Three");
ht.Add("4", "Four");
foreach (var k in ht.Keys)
{
Console.WriteLine(k);
}
I see no sorting of any kind taking place.

Hashtables do not preserve the order of inserted items. They are stored in a data structure that has no concept of a "correct" order. You should assume that items in a hashtable will be stored in a random order.
You should use a List or other structure instead of a Hashtable if the order of the items is important.

Try this:
Hashtable ht = new Hashtable();
ht.Add("1", "One");
ht.Add("2", "Two");
ht.Add("3", "Three");
ht.Add("4", "Four");
foreach (var k in ht.Keys.sort)
{
Console.WriteLine(k);
}
Notice the sort after ht.Keys

To get the Values in your hashtable ordered by key (wich is what it looks like you want) use this:
public List<string> GetOrderedValues(HashTable ht)
{
// Get a sorted list of keys
List<string> keys = new List<string>(ht.Keys.Cast<string>());
keys.Sort();
// Get values sorted by key
List<string> values = new List<string>();
foreach (string key in keys)
values.Add(ht[key]);
// Return Sorted Values
return values;
}
You can also separete the first part and then you can get both a list of sorted keys and a list of sorted values.
Another option is return a List of KeyValuePair wichh will be sorted by entry
Then again, why not just remove all the ashle and replace your hashtable with a List of KeyValuePair in the first place?

I found this blog, http://mctexpert.blogspot.com/2014/12/keeping-hash-table-in-order.html
To be specific, using [Ordered] would help with keeping the original sort:
$Hash = [Ordered]#{"Apple"="Red";
"Orange"="Orange";
"Banana"="Yellow";
"Pear"="Green";
"Blueberry"="Blue";
"Plum"="Purple"}

Related

How to add keys to hashtable from a List in the same order in C#

I have a integer List List<int> iFaciltyReqId = new List<int>(); and its elements are
I need to order the hashtable below like the above List(need to exclude if the element not exist)
My hashtable is
Result should be hastable keys in the order
1153
1168
1155
1152
1176
676
I tried as below, but the result is not meeting my expectation
foreach (var c in iFaciltyReqId)
{
foreach (var d in ohmItemSeqs.Keys)
{
if (Convert.ToInt32(c) == Convert.ToInt32(d))
{
sortedohmItemSeqs.Add(c, ohmItemSeqs.Values);
}
}
}
and result was
Any help will be appreciated.
I would suggest you simply take your list and return everything that's also in the hash table like so:
var result = yourList.Where(i => yourHashTable.Contains(i)); // works for both HashSet<int> and Hashtable
A Hashtable is fundamentally an unordered data structure, so you'll want to look at alternatives if maintaining order is important.
If you want the order to be determined by insertion, OrderedDictionary may be a suitable option, although that depends on what your other needs for the object are.

Sorting a dictionary by keys in the order in an Arraylist

I was asked the following question in an interview. How can I sort a Dictionary by the key, in the order which is in an array list.
So for example I have a dictionary as follows
Dictionary<string, string> stringDict = new Dictionary<string, string>();
stringDict.Add("1", "One");
stringDict.Add("7", "Seven");
stringDict.Add("6", "Six");
stringDict.Add("2", "Two");
stringDict.Add("3", "Three");
stringDict.Add("5", "Five");
stringDict.Add("4", "Four");
And an array list as follows
ArrayList stringArList = new ArrayList();
stringArList.Add("1");
stringArList.Add("2");
stringArList.Add("3");
stringArList.Add("5");
stringArList.Add("6");
stringArList.Add("7");
stringArList.Add("4");
How can I sort the dictionary in the order it is in the array list?
Well you can't sort a Dictionary per se, but you can extract the key-values pairs as a list and sort those:
IEnumerable<KeyValuePair<string, string>> pairs =
stringDict.OrderBy(kvp => stringArList.IndexOf(kvp.Key));
But there's not a way to "traverse" dictionary items in any particular order.
You could create a SortedDictionary and provide an IComparer<string>
var d = new SortedDictionary<string, string>(stringDict,
new PositionComparer(stringArList));
With the Comparer implementation as:
public class PositionComparer : IComparer<string>
{
private ArrayList Keys {get; set;}
public PositionComparer(ArrayList keys)
{
Keys = keys;
}
public int Compare(string s1, string s2)
{
return Keys.IndexOf(s1).CompareTo(Keys.IndexOf(s2));
}
}
This will produce a list of the values sorted as required.
var sortedValues = stringDict.OrderBy(pair => stringArList.IndexOf(pair.Key))
.Select(pair => pair.Value)
.ToList();
As said many times before in this question, a C# Dictionary can not be sorted. This is inherent to the implementation. As you can read here, the dictionary is implemented using a Hashtable. This means that those items don't have any ordering. You can't say "give me the first element of this dictionary". There simply is no first, second or last element. The only thing you can say about an element in a dictionary is that it has a unique identifier which determines it's location in the dictionary (with a little help from the hash function).
When you have an element in an array for example, you can say "this element is the next element" or "this element is the previous element". Each element in an array has a previous and a next. This does not hold for dictionaries.
When you insert an item into the dictionary it will generate a hash (a fairly unique number) based on the key. For example, a very simple (and bad) hash of keys consisting of names would be to take the sum of each character presented as their ASCII value in the name, and then add those together. The result is a number, say 5, then we would insert the value in a store (an array for example) on position 5. If however, at position 5 is another value, which happens to have the same hash result you have a collision. How you solve these, and how you avoid these is what hashtables are all about. See the Wiki for more information on this.
When you request your value with your key someName it will hash that value and look it up at that position.
Hashtables are not as easy as I just explained, there is a lot too it. You can read more on the Wiki.
So the answer to "Sort this dictionary" is most definitely "No can do.". However, you can convert it to a sortable data structure like a list, or whatever and then sort it.
I replied with the following answer.
var list = from arElement in stringArList.ToArray().ToList()
join dict in stringDict on arElement equals dict.Key
select dict ;
But the interviewer didn't seem to be impressed.
original_dic.OrderBy returns IOrderedEnumerable, that you convert to a new dictionary.
var ordered_dic = original_dic.OrderBy(x => x.Key).ToDictionary(x=> x.Key, x=> x.Value);

How delete items from Dictionary

I have
Dictionary<string, List<string>> Dic = new Dictionary<string, List<string>>();
How delete first 1,2,3 elements From Dic. I dont know how make it with "foreach"
foreach (KeyValuePair<string, List<string>> kvPair in Dic)
{
Console.WriteLine(kvPair.Key);
foreach (string str in kvPair.Value)
{
}
}
You can't get item 1,2,3 from the dictionary, you can only remove on the basis of a key.
Dictionary MSDN
The order in which the items are returned is undefined.
You may use Orderby to sort the dictionary on the basis of a key. But to remove an item from the dictionary you will need the key.
See Dictionary.Remove
EDIT: based on your edited question with "foreach"
You can't modify the dictionary while enumerating on it. If you try removing items from the dictionary in the foreach you will get error:
Collection was modified; enumeration operation may not execute.
You may convert the dictionary to an array and then remove the items from the dictionary (something like below, it may be improved or changed, it is just for an idea):
var dicArrray = Dic.ToArray();
foreach (KeyValuePair<string, List<string>> kvPair in dicArrray)
{
if (kvPair.Key.Equals("1"))
Dic.Remove(kvPair.Key);
}
But remember, the order in which the items will be in array is undefined. You can't be sure about it
as habib says you can not delete item from dictionary based upon index, you can only remove item based upon the key, use Remove() method
read more from here- Remove Item in Dictionary based on Value
first, create a collection of keys you want to remove:
var toDelete = new List<string>();
int count = 3;
foreach(var pair in dictionary) {
toDelete.Add(pair.Key);
count -= 1;
if( count==0 ) break;
}
// then when ready - delete
foreach(string key in toDelete) dictionary.Remove(key);
the reason is not to invalidate dictionary enumerator by removing items while enumerating.
also consider that order in which key pairs appear is not explicitly set in specification, so you may not rely on it - even if it works now it may stop working in a next version of framework. Thus you have also to decide what does "first 3" means before creating a list of elements to delete.
To remove an item in a dictionary, use the Remove() method. For example:
Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
dictionary.Add("1", new List<string());
dictionary.Remove("1");
The order dictionary elements are added is not maintained. However, if you want to delete the highest key, for example, do something like:
dictionary.Remove(dictionary.Keys.OrderBy().First());
If dic is a "simple" Dictionary, using LINQ you can create a new dictionary from the original and reassign it to dic, like this:
dic = dic.Skip(3).ToDictionary(kv => kv.Key, kv => kv.Value);
As pointed out by astander in a comment and in Habib's answer, the order of the dictionary items is undefined, so you might want to apply this technique on a SortedDictionary only.
In that case, you would need to create a new SortedDictionary from the LINQ result:
dic = new SortedDictionary<string, List<string>>(
dic.Skip(3).ToDictionary(kv => kv.Key, kv => kv.Value));

Can Dictionary values be populated through a list without looping?

Can we have something like -
Dictionary<string, string> dict = new Dictionary<string, string>();
List<string> keysList= new List<string>();
List<string>valuesList= new List<string>();
//Assuming both the list have the same number of items
dict.keys = keysList;
dict.values = valuesList;
Mostly, I want to know if there is a way to populate the keys and values by directly assigning them to a list?
Mostly, I want to know if there is a way to populate the keys and values by directly assigning them to a list?
No, but just zip them and then use ToDictionary:
var dict = keysList.Zip(valuesList, (key, value) => Tuple.Create(key, value))
.ToDictionary(pair => pair.Item1, pair => pair.Item2);
A dictionary, internally isn't storing the data as two lists. It's storing the data in a hash table, which means it need to take each key, generate a hash for it, and then place the item at the location that corresponding to that hash. Because of this the only way to add a group of items is just to loop through the group and add each item. You can use the LINQ ToDictionary method, as mentioned in another answer, but internally all it's going to do is loop through each item and add it to the dictionary. This prevents you from seeing the loop, but the loop is still there.

The order of elements in Dictionary

My question is about enumerating Dictionary elements
// Dictionary definition
private Dictionary<string, string> _Dictionary = new Dictionary<string, string>();
// add values using add
_Dictionary.Add("orange", "1");
_Dictionary.Add("apple", "4");
_Dictionary.Add("cucumber", "6");
// add values using []
_Dictionary["banana"] = 7;
_Dictionary["pineapple"] = 7;
// Now lets see how elements are returned by IEnumerator
foreach (KeyValuePair<string, string> kvp in _Dictionary)
{
Trace.Write(String.Format("{0}={1}", kvp.Key, kvp.Value));
}
In what order will be the elements enumerated? Can I force the order to be alphabetical?
The order of elements in a dictionary is non-deterministic. The notion of order simply is not defined for hashtables. So don't rely on enumerating in the same order as elements were added to the dictionary. That's not guaranteed.
Quote from the doc:
For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair<TKey, TValue> structure representing a value and its key. The order in which the items are returned is undefined.
You can always use SortedDictionary for that. Note that the dictionary is ordered by Key, by default, unless a comparer has been specified.
I'm skeptic regarding the use of OrderedDictionary for what you want since documentation says that:
The elements of an OrderedDictionary are not sorted by the key, unlike
the elements of a SortedDictionary class.
If you want the elements ordered, use a SortedDictionary. An ordinary hastable/dictionary is ordered only in some sense of the storage layout.
The items will be returned in the order that they happen to be stored physically in the dictionary, which depends on the hash code and the order the items were added. Thus the order will seem random, and as implementations change, you should never depend on the order staying the same.
You can order the items when enumerating them:
foreach (KeyValuePair<string, string> kvp in _Dictionary.OrderBy(k => k.Value)) {
...
}
In framework 2.0 you would first have to put the items in a list in order to sort them:
List<KeyValuePair<string, string>> items = new List<KeyValuePair<string, string>>(_Dictionary);
items.Sort(delegate(KeyValuePair<string, string> x, KeyValuePair<string, string> y) { return x.Value.CompareTo(y.Value); });
foreach (KeyValuePair<string,string> kvp in items) {
...
}
For an OrderedDictionary:
var _OrderedDictionary = new System.Collections.Specialized.OrderedDictionary();
_OrderedDictionary.Add("testKey1", "testValue1");
_OrderedDictionary.Add("testKey2", "testValue2");
_OrderedDictionary.Add("testKey3", "testValue3");
var k = _OrderedDictionary.Keys.GetEnumerator();
var v = _OrderedDictionary.Values.GetEnumerator();
while (k.MoveNext() && v.MoveNext()) {
var key = k.Current; var value = v.Current;
}
Items are returned in the order that they are added.
Associative arrays (aka, hash tables) are unordered, which means that the elements can be ordered in any way imaginable.
HOWEVER, you could fetch the array keys (only the keys), order that alphabetically (via a sort function) and then work on that.
I cannot give you a C# sample because I don't know the language, but this should be enough for you to go on yourself.

Categories

Resources