131

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?

Captain Comic
  • 15,744
  • 43
  • 110
  • 148
  • 1
    possible duplicate of [Does the Enumerator of a Dictionary return key value pairs in the order they were added? .Net](http://stackoverflow.com/questions/1453190/does-the-enumerator-of-a-dictionarytkey-tvalue-return-key-value-pairs-in-the) – nawfal Oct 31 '13 at 07:59
  • Related: [Why is a Dictionary “not ordered”?](https://stackoverflow.com/questions/6384710/why-is-a-dictionary-not-ordered) – Theodor Zoulias Dec 02 '20 at 05:24

6 Answers6

149

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.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 6
    But [there is OrderedDictionary](https://stackoverflow.com/questions/4007782/the-order-of-elements-in-dictionary/4007799#4007799). – Peter Mortensen Jan 20 '19 at 12:05
35

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Adriano Carneiro
  • 57,693
  • 12
  • 90
  • 123
  • It's important to note that `SortedDictionary` is implemented as a Binary Search Tree, which gives its operations different time and space complexity compared to the hashtable-based `Dictionary`. If users need an `O(1)` insert/delete hashtable structure and also want to iterate over elements in key-order then they should to `dict.Keys.OrderBy( k => k ).Select( k => dict[k] )` instead (at the cost of `O(n)` space and `O( n log n )` time) for the `OrderBy()` (which will need to buffer the entire keys collection in an internal list). – Dai Oct 14 '19 at 22:56
32

If you want the elements ordered, use a SortedDictionary. An ordinary hastable/dictionary is ordered only in some sense of the storage layout.

Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
  • 12
    OrderedDictionary is in most cases wrong. It is neither Ordered by key or value, but by an internal Index. SortedDictionary is the one which is ordered in a way the user can manipulate (default key) – Offler May 29 '15 at 09:01
  • 4
    The question is asking about ordering in alphabetical order (assuming the questioner is talking about the key). An ordered dictionary, if I understand the documentation correctly, will spit out the elements in the order they are inserted, i.e. not alphabetical, but using the internal index. A SortedDictionary is probably the best fit for the user's question. – mattpm Mar 15 '18 at 00:30
15

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.

Mariusz Jamro
  • 30,615
  • 24
  • 120
  • 162
Barton
  • 547
  • 5
  • 11
14

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) {
  ...
}
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
5

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.

Tim Čas
  • 10,501
  • 3
  • 26
  • 32