Changing the Order in a .NET Generic Dictionary - c#

I have a class that inherits from a generic dictionary as follows:
Class myClass : System.Collections.Generic.Dictionary<int, Object>
I have added a list of values to this in a particular order, but I now wish to change that order. Is there any way (without removing and re-adding) that I could effectively re-index the values; so change the object at index 1 to now be at index 10 for example? For example, this doesn't work:
myClass[1].Index = 10;

Have a look at the SortedDictionary class where you can sort your items by the key.
Normally, you cannot change the index of items in Dictionary because it is against the principle ;-)

Dictionaries by themselves don't have an index order. Consider inheriting from the KeyedCollection class instead. It's a merge of a dictionary and an ordinary list, and it's designed to use a member of your items as the key, and have an index order.

Dictionaries (or more generally hashtables) do not have indicies. This goes for all languages.

For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair structure representing a value and its key. The order in which the items are returned is undefined.
Taken from MSDN.

Old topic, but nevertheless the answers are not all valid
You can use Linq to achieve this.
Dictionary<int, string> Breadcrumbs = new Dictionary<int, string>();
Breadcrumbs.Add(1, "Test1");
Breadcrumbs.Add(2, "Test2");
Breadcrumbs.Add(3, "Test3");
Breadcrumbs.Add(4, "Test4");
Breadcrumbs.Add(5, "Test5");
var q = Breadcrumbs.OrderByDescending(x => x.Key);
// And bind it
gridView.DataSource = q;
gridView.DataBind();

Take a look at this question. Not a duplicate but I think it fully applies to you. They suggest you have two collections: both a dictionary (for lookups) and a List (for keeping an order that isn't sortable). If these are reference types, then you shouldn't be too concerned about memory usage here since you're only duplicating pointers (unless, of course, you have a bajillion items in here).

Dictionary<> is an unordered collection, you'll only get the elements out of it in the order you put them in by accident. You'll need a SortedDictionary<>.

I have added a list of values to this in a particular order
There is no such thing like particular order for Dictionary.
Perhaps you can look at SortedList. It supports indexing for keys and values but adding / removal are O(n) complexity vs O (log N) for SortedDictionary.

Related

Which generics should I use

I need to store a list of int-string key-value pairs with a requirement to preserve the order in which items were added. Once it is initialized, it does not change, i.e. nothing added or removed..
At first I thought of using Dictionary<int,string> and everytime I need to access the items use
foreach(var entry in dict.OrderBy(e=>e.Key)) { } //as Key is `int`
However everytime ordering does not seem to be the best option to use.
Now I've come to an idea to have a List<Tuple<int, string>>, as soon as List<T> guarantees the order of items.
So, is there a better option?
Looking at the proposed possibilities:
Dictionary doesn't guarantee the order of the items
SortedDictionary sorts the items, but not in the order you added them (it sorts based on key comparison),
OrderedDictionary keeps the order, but it's not generic and would introduce unnecessary casting and boxing.
So I think you should use List<Tuple<int, string>>. It preserves order and it's good enough for iteration using foreach and indexed access. If you know the size in advance, you could use an array as well, or a read only collection type, as Cuong Le suggested in his answer.
If you allow duplicate key, List<Tuple<int, string>> would be the best choice. In order make your list as read-only, you can public read-only list after initialization:
var readonlyList = new ReadOnlyCollection<Tuple<int, string>>(yourlist);
Although Dictionary seems suitable as a data structure, it does not guarantee order of items.
List does not seem proper as it does not fit well with the data structure you are trying to store.
You may use an OrderedDictionary which guarantees the order of items.
foreach (DictionaryEntry entry in orderedDictionary)
{
//...
}

Iterating over Dictionary with foreach, in what order is this done?

Say I have a Dictionary, and I add each key and value entry in a specific order.
Now, if I want later to be able to iterate this Dictionary in the same order entries were added, is it the order I get with simple foreach loop on this dictionary?
If not, I will be glad to hear how can I do that, I know this can be done easily with List instead of Dictionary but I don't want to.
Thanks
Normal Dictionary does not guarantee order of items.
You need OrderedDictionary if you want to maintain order items where added to it. Note that there is no generic version of this class in .Net framework, so either have to give up some type-safety or find other implementation (i.e. https://www.codeproject.com/Articles/18615/OrderedDictionary-T-A-generic-implementation-of-IO as suggested by Tim S).
Alternatively if O(log n) lookup is fine and keys should be sorted - SortedDictionary.
Sounds like what you want is a Queue<T>: http://msdn.microsoft.com/en-us/library/7977ey2c.aspx
Add your KeyValuePair<T, U> items to it in the order you want and then foreaching over it will be in first-in/first-out order.
Dictionarys are hash tables, which means that you can't guarantee that iterating the pairs will return them in the same order you added them.
Each pair is a KeyValuePair<T_K, T_V>, so you could have a List<KeyValuePair<string, string>> that would let you iterate in the order you add them if that's what you need.
The internal sort of the dictionary will depend on the hash function used. However if you need a sorted view of the data, you can use Enumerable.OrderBy.

How to insert a key/value pair into a dictionary?

When I add an entry to a Dictionary using Add, the KeyValuePair is added at the end of it. I would like to preppend it thus when I iterate on KeyValuePair's, it is the first item.
Is there a way to do it with a Dictionary or should I build a List<KeyValuePair<TKey, TValue>> or do you have a better proposition?
EDIT : I thought I could work on the enumeration in Dictionary, it seems I can't.
I tried with List<KeyValuePair<TKey, TValue>> which was not very practical.
The Dictionary class doesn't have a concept of order within it - there is no positional index to the Dictionary.
Take a look at the OrderedDictionary class in the System.Collections.Specialized namespace if you need to use a positional index on a dictionary.
I think you're looking for the OrderedDictionary.
Use OrderedDictionary.
Represents a collection of key/value pairs that are accessible by the key or index. You can insert the key value pait at desired index.
If you are looking to preserve order, Dictionary is not the collection that you want to use (it doesn't have a concept of order).
There is an OrderedDictionary collection that will help if you need to have an indexed dictionary.
There is also a SortedDictionary collection, that will sort the values that you add based on the key value.
Officially, you can never know in what order your key-value pairs will come out of a Dictionary<,> if you iterate through it (foreach it, thereby calling GetEnumerator()). And certainly, if you Remove some items from your dictionary, and later Add some other items, when you foreach your way through the collection, the new items will be in the space of the removed items, not in the end of the iteration "list".
But: If you know you never Delete from your Dictionary<,>, it looks like the enumeration yields the items in the order they were added. There is no guarantee this will always work, but it looks like it works in the current implementation.
So if you dare rely on this, you could just say
foreach (var keyValuePair in myDict.Reverse())
{
...
The Reverse method is part of LINQ (needs using System.Linq).

Is there an data type that acts both as a list and a dictionary?

Normally when I need to have a list of ints/strings/etc. I create a list like:
var list = new List<string>
And then I create a hashtable that contains all the strings, and I don't insert into the list unless it isn't in the hashtable i.e. to enforce unique items in the list.
Is there a datatype that can satisfy both of these requirements for me?
There is. Use HashSet:
var set = new HashSet<int>();
set.Add(4);
set.Add(4); // there is already such an element in the set, no new elements added
Keep in mind, though, that it does not guarantee you the order of elements.
Do you just mean HashSet<string> ?
All elements in a HashSet<T> are unique; the Add() method returns a bool to indicate if a new item was actually added, or whether it was a no-op.
Is there a datatype that can satisfy both of these requirements for me?
No. A hashtable will provide you a direct access to an element given its unique key, whereas in a list you don't need a key and you could definitely have duplicates.
You can use the HashSet<T> data type MSDN. Which will only allow you to have a single copy of each value.
If you are after a set of unique values only (and don't subsequently care about ordering) then you should look at a HashSet<T>
Technically, there is System.Collections.Specialized.OrderedDictionary. However, this is an old non-updated (non-generic) class and I would generally recommend avoiding it ;-)
Represents a collection of key/value pairs that are accessible by the key or index.
In practice I would create a minimal wrapper class that exposes the required operations. (I would likely use a HashSet<T> (for existence) and a List<T> (for ordering), although just a single List<T> is far than sufficient for a relatively small n in most cases -- remember Big-O is about limits.)
Happy coding.
HashSet<string> set = new HashSet<string>();
bool inserted = set.Add("Item");
bool insertedDuplicate = set.Add("Item");
inserted.Dump("Result1");
insertedDuplicate.Dump("Result2");
//Result
//Result1 = true
//Result2 = false
You can run this in LinqPad to see the functionality and how it works.

C# Reverse items in Dictionary

I'm trying to reverse items in a dictionary in C#.
I have tried:
Dictionary<double, int> dict = new Dictionary<double, int>();
...add itmes to it....
var v = dict.Reverse()
However, dict.Reverse() gives me a type of IEnumberable>. I was just wondering how I could make it to a type of Dictionary?
Thanks in advance.
Stop!
Dictionaries and hashtables and sets have no ordering.
There is absolutely no point in sorting or changing the order.
A Dictionary isn't an ordered data structure. For Reverse to have any real meaning you'll need to use a SortedDictionary. You can get a reversed copy of a SortedDictionary by creating a new one with a Comparer that does the opposite sorting to the original (see constructor).
var reversed = new SortedDictionary( original, new ReverseKeyComparer() );
Note that ReverseKeyComparer is a ficticious class for the example.
Also - you need to know that the SortedDictionary is somewhat of a misnomer, if you equate Dictionary to map or hashtable. It uses a binary tree implementation (Red-Black, I think) with different algorithmic complexity than the hashtable implementation of Dictionary. See the Remarks sections of their respective documentation pages. If performance is critical, you might want to consider whether the ordering is truly important.
If you want dictionaries to have a certain order, you should look into SortedDictionary.
See this article.

Categories

Resources