Changing the power of an element in a C # dictionary

I have a dictionary, something like

Dictionary<Foo,String> fooDict 

I look through all the words in the dictionary, for example.

 foreach (Foo foo in fooDict.Keys) MessageBox.show(fooDict[foo]); 

It does this in the order in which foos were added to the dictionary, so the first element added is the first foo returned.

How can I change the power so that, for example, the third added foo is the second returned foo? In other words, I want to change my "index".

+4
source share
5 answers

If you read the MSDN documentation, you will see the following:

"The order in which elements are returned is undefined."

You cannot complete an order because the dictionary is not a list or an array. This meant finding the value with the key, and any possibility of iterating over the values ​​is just a convenience, but order is not the behavior you should depend on.

+8
source

You might be interested in the OrderedDicationary class, which comes in System.Collections.Specialized .

If you look at the comments at the bottom, someone from MSFT posted this interesting note:

This type is actually incorrectly named; it is not an "ordered" dictionary as such, but rather an "indexed" dictionary. Although there is no equivalent generic version of this type today, if we add it in the future, we will probably call this type IndexedDictionary.

I think it would be trivial to infer this class and create a generic version of OrderedDictionary.

+5
source

I am not fully educated in the domain to correctly answer the question, but I have a feeling that the dictionary sorts the values ​​according to the key in order to perform a quick search for the keys. This assumes that the dictionary is sorted by key values ​​according to key mapping. However, looking at the object methods, I assume that they use hash codes to compare different objects, given that there is no requirement for the type used for keys. This is just an assumption. Someone should fill out more knowledge in more detail.

Why are you interested in manipulating the "index" of a dictionary when its purpose is to index with arbitrary types?

0
source

I don’t know if anyone will find this useful, but here is what I found out. This seems to work (I mean that it does not throw any exceptions), but I'm still not able to verify that it works as I hope. However, I did something similar.

  public void sortSections() { //OMG THIS IS UGLY!!! KeyValuePair<ListViewItem, TextSection>[] sortable = textSecs.ToArray(); IOrderedEnumerable<KeyValuePair<ListViewItem, TextSection>> sorted = sortable.OrderBy(kvp => kvp.Value.cardinality); foreach (KeyValuePair<ListViewItem, TextSection> kvp in sorted) { TextSection sec = kvp.Value; ListViewItem key = kvp.Key; textSecs.Remove(key); textSecs.Add(key, sec); } } 
0
source

The short answer is that there should be no way, because the dictionary "Represents a collection of keys and values." which does not imply any orders. Any hack you can find is outside the class definition and can be changed.

You should probably first ask yourself if a dictionary is really needed in this situation, or if you can use the KeyValuePairs list.

Otherwise, the following may be useful:

 public class IndexableDictionary<T1, T2> : Dictionary<T1, T2> { private SortedDictionary<int, T1> _sortedKeys; public IndexableDictionary() { _sortedKeys = new SortedDictionary<int, T1>(); } public new void Add(T1 key, T2 value) { _sortedKeys.Add(_sortedKeys.Count + 1, key); base.Add(key, value); } private IEnumerable<KeyValuePair<T1, T2>> Enumerable() { foreach (T1 key in _sortedKeys.Values) { yield return new KeyValuePair<T1, T2>(key, this[key]); } } public new IEnumerator<KeyValuePair<T1, T2>> GetEnumerator() { return Enumerable().GetEnumerator(); } public KeyValuePair<T1, T2> this[int index] { get { return new KeyValuePair<T1, T2> (_sortedKeys[index], base[_sortedKeys[index]]); } set { _sortedKeys[index] = value.Key; base[value.Key] = value.Value; } } } 

With client code, it looks something like this:

  static void Main(string[] args) { IndexableDictionary<string, string> fooDict = new IndexableDictionary<string, string>(); fooDict.Add("One", "One"); fooDict.Add("Two", "Two"); fooDict.Add("Three", "Three"); // Print One, Two, Three foreach (KeyValuePair<string, string> kvp in fooDict) Console.WriteLine(kvp.Value); KeyValuePair<string, string> temp = fooDict[1]; fooDict[1] = fooDict[2]; fooDict[2] = temp; // Print Two, One, Three foreach (KeyValuePair<string, string> kvp in fooDict) Console.WriteLine(kvp.Value); Console.ReadLine(); } 

UPDATE: For some reason, he will not allow me to comment on my own answer.

In any case, IndexableDictionary differs from OrderedDictionary in that

  • "OrderedDictionary elements are not sorted in any way." Therefore foreach would not pay attention to numeric indices
  • It is strongly typed, so you don’t have to bother with customization from DictionaryEntry structures.
0
source

Source: https://habr.com/ru/post/1277135/