FSm
FSm

Reputation: 2057

Getting index of dictionary item based on item.key

How can I find the index of an element of a dictionary based on the element key? I'm using the following code to go through the dictionary:

foreach (var entry in freq)
{
    var word = entry.Key;
    var wordFreq = entry.Value;
    int termIndex = ??????;
}

Could anyone help please?

Upvotes: 15

Views: 55872

Answers (8)

Ondrej Rozinek
Ondrej Rozinek

Reputation: 601

The dictionary implementation in .NET hashtable has no defined index because it is based on a hash key. I find the answers here to be inefficient and slow because many of these solutions do not preserve the time complexity of the O (1) Dictionary data structure. The ordered dictionary has some performance disadvantages compared to the dictionary.

The only once efficient possible solution is to add an index while building the dictionary. So you should have e.g.

Dictionary<string, Tuple <int, int >>

where in the tuple you would add an index if you add a new key-value pair. This simple solution preserves the time O (1) and in addition you can have a property with an index.

Upvotes: 0

dylful
dylful

Reputation: 89

This might work and this is probably not the most efficient way of doing this. Also im not sure why you would want something like this.

Int termIndex = Array.IndexOf(myDictionary.Keys.ToArray(), someKey);

Upvotes: 7

Raiven66
Raiven66

Reputation: 111

It's old but someone might use it - I currently use

public static int OrderedDictIndexOfKey(string key, OrderedDictionary oDict)
{
    int i = 0;
    foreach (DictionaryEntry oDictEntry in oDict)
    {
        if ((string)oDictEntry.Key == key) return i;
        i++;
    }

    return -1;
}

public static object OrderedDictKeyAtIndex(int index, OrderedDictionary oDict)
{
    if (index < oDict.Count && index >= 0)
    {
        return oDict.Cast<DictionaryEntry>().ElementAt(index).Key;
    }
    else
    {
        return null;
    }
}

Upvotes: 1

Vakun
Vakun

Reputation: 231

There is 2 extension methods

Index by key

public static int IndexOf<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key) 
    {
        int i = 0;
        foreach(var pair in dictionary)
        {
            if(pair.Key.Equals(key))
            {
                return i;
            }
            i++;
        }
        return -1;
    }

Index by value

public static int IndexOf<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TValue value) 
    {
        int i = 0;
        foreach(var pair in dictionary)
        {
            if(pair.Value.Equals(value))
            {
                return i;
            }
            i++;
        }
        return -1;
    }

Upvotes: 4

rasputino
rasputino

Reputation: 799

Maybe something like this could work:

public static int GetIndex(Dictionary<string, object> dictionary, string key) 
{
    for (int index = 0; index < dictionary.Count; index++)
    {
        if(dictionary.Skip(index).First().Key == key)
            return index;
    }

    return -1;
}

Based on Dennis Traub solution, but using a Dictionary... (it's orderer by the original addition)

Upvotes: 3

Dennis Traub
Dennis Traub

Reputation: 51634

There is no concept of an index in a Dictionary. You can't rely on any order of items inside the Dictionary. The OrderedDictionary might be an alternative.

var freq = new OrderedDictionary<string, int>();
// ...

foreach (var entry in freq)
{
    var word = entry.Key;
    var wordFreq = entry.Value;
    int termIndex = GetIndex(freq, entry.Key);
}


public int GetIndex(OrderedDictionary<string, object> dictionary, string key) 
{
    for (int index = 0; index < dictionary.Count; index++)
    {
        if (dictionary.Item[index] == dictionary.Item[key]) 
            return index; // We found the item
    }

    return -1;
}

Upvotes: 10

Warlock
Warlock

Reputation: 7471

There is no way to get index, since data storing in memory in absolutely different ways for array and dictionary.

When you declare array of any type, you know, that data will be placed in memory cells one after the other. So, index is a shift of memory address.

When you put data in a dictionary, you can't predict the address, that will be used for this item, because it will be placed in specific empty position, which will provide balanced graph for fast search by key. So, you can't manipulate with dictionary data using index.

P.S. I believe, that you can resolve your problem using Linq.

Upvotes: 6

Richard
Richard

Reputation: 22016

As Dennis states there is no index in dictionary but in your example the position in the foreach loop could be tracked as so:

int index = -1;
foreach (var entry in freq)
            {

                var word = entry.Key;
                var wordFreq = entry.Value;
                int termIndex = ++index;


            }

Upvotes: 1

Related Questions