7

This is similar to How to keep the order of elements in hashtable, except for .NET.

Is there any Hashtable or Dictionary in .NET that allows you to access it's .Index property for the entry in the order in which it was added to the collection?

Community
  • 1
  • 1
Todd Main
  • 28,951
  • 11
  • 82
  • 146

6 Answers6

6

A NameValueCollection can retrieve elements by index (but you cannot ask for the index of a specific key or element). So,

var coll = new NameValueCollection();
coll.Add("Z", "1");
coll.Add("A", "2");
Console.WriteLine("{0} = {1}", coll.GetKey(0), coll[0]); // prints "Z = 1"

However, it behaves oddly (compared to an IDictionary) when you add a key multiple times:

var coll = new NameValueCollection();
coll.Add("Z", "1");
coll.Add("A", "2");
coll.Add("Z", "3");
Console.WriteLine(coll[0]); // prints "1,3"

The behaviour is well documented, however.

Caution: NameValueCollection does not implement IDictionary.


As an aside: Dictionary<K,V> does not have any index you can use, but as long as you only add elements, and never remove any, the order of the elements is the insertion order. Note that this is a detail of Microsoft's current implementation: the documentation explicitly states that the order is random, so this behavior can change in future versions of the .NET Framework or Mono.

Ruben
  • 15,217
  • 2
  • 35
  • 45
4

If this is something that you need to keep track of efficiently, then you are using the wrong data structure. Instead, you should use a SortedDictionary where the key is tagged with the index of when it was added (or a timestamp) and a custom IComparer that compares two keys based on the index (or the timestamp).

jason
  • 236,483
  • 35
  • 423
  • 525
4

Is there any Hashtable or Dictionary in .NET that allows you to access it's .Index property for the entry in the order in which it was added to the collection?

No. You can enumerate over all the items in a Hastable or Dictionary, but these are not guaranteed to be in any sort of order (most likely they are not)

You would have to either use a different data structure altogether, (such as SortedDictionary or SortedList) or use a separate list to store the order in which they were added. You would want to wrap the ordered list and your dictionary/hashtable in another class to keep them synched.

Neil N
  • 24,862
  • 16
  • 85
  • 145
4

You can use a separate list to store the elements in the order they are added. Something along the lines of the following sample:

public class ListedDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
    List<TValue> _list = new List<TValue>();
    Dictionary<TKey, TValue> _dictionary = new Dictionary<TKey,TValue>();

    public IEnumerable<TValue> ListedValues
    {
        get { return _list; }
    }

    public void Add(TKey key, TValue value)
    {
        _dictionary.Add(key, value);
        _list.Add(value);
    }

    public bool ContainsKey(TKey key)
    {
        return _dictionary.ContainsKey(key);
    }

    public ICollection<TKey> Keys { get { return _dictionary.Keys; } }

    public bool Remove(TKey key)
    {
        _list.Remove(_dictionary[key]);
        return _dictionary.Remove(key);
    }

    // further interface methods...
}
Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
2

Take a look at the OrderedDictionary class. Not only can you access it via keys, but also via an index (position).

Diego Barros
  • 2,071
  • 2
  • 33
  • 45
1

An alternative is to create an array of stuctures, so instead of using

dictionary.Add{"key1","value1"}

you create a structure with the key/value like:

public struct  myStruct{
    private string _sKey;
    public string sKey{
        get { return _sKey; }
        set { _sKey = value; }
    }
    private string _sValue;
    public string sValue {
        get { return _sValue; }
        set { _sValue = value; }
    }
}

// create list here
List<myStruct> myList = new List<myStruct>();

// create an instance of the structure to add to the list
myStruct item = new myStruct();
item.sKey = "key1";
item.sValue = "value1";

// then add the structure to the list
myList.Add(item);

Using this method you can add extra dimensions to the list without too much effort, just add a new member in the struct.

Note, if you need to modify items in the list after they have been added you will have to change the struct into a class. See this page for more info on this issue: error changing value of structure in a list

Myke Black
  • 1,299
  • 15
  • 15