开发者

How to get the relative position of a Dictionary element?

I have the next C# code:

    Dictionary<string, int> d = new Dictionary<string, int>();
    d.Add("a", 3);
    d.Add("b", 1);
    d.Add("c", 0);
    d.Add("d", -1);
    d.Add("e", -9);

When searching the key "c" I want to get the position of this key, i.e. 2. If I look for the key "e", I want to get 4. If the element is not found the relative position could be -1.

Added: Unless you have a better idea, I want to populate a matrix with certain values in a开发者_JAVA百科 row number indicated by the relative position of a dictionary element found. The same applies for the column but using a different dictionary. An example:

     n4   n2   n1   n3  n9  . . . 
a   4/4
b              2         8
c
d                  8/2
e         4/3
.
.
.

Where a,b,c,d,e,... are the keys of dictionay "d" and n4,n2,n3,n9 are the keys of a second dictionary.

How can I get this?


There's no such thing as a "position" within a Dictionary<,> - it's an unordered collection.

There are similar collections sorted by key - SortedList<,> and SortedDictionary<,>. Note that those are ordered by key rather than insertion time though. It's not clear which you want.


This should do the trick:

d.Keys.ToList().IndexOf("c");

Please Note that the O(1) time lookup offered by the Dictionary is lost when converting to the List, because Lists are inherently O(n). So if your Dictionary has a large number of elements, you're probably better off using another Dictionary or Matrix dimension to store the positions, since retrieving them in this manner will likely be slower. In fact, you should probably assume that the one-liner above is similar to:

GetDictKeyPos(d, "c");

public int GetDictKeyPos(Dictionary<string, int> d, string key)
{
    for (int i = 0; i < d.Count; ++i)
    {
        if (d.ElementAt(i).Key == key)
            return i;
    }
    return -1;
}

As a side note, if you are trying to get the position, you're probably making the assumption that the position is preserved. Microsoft says don't count on it, but in practice you'll discover that you probably can count on it. (I've never seen position not be preserved.) That being said, until Microsoft admits that, "Yeah, yeah, we've been holding out on you: position actually is preserved in a Dictionary. We just didn't want to admit it because we wanted to be able to change it if we found a better implementation, but now we know we're going to leave it, so here ya go...", you probably shouldn't assume that position is preserved.

Lastly, if you are planning to take your chances and assume it's preserved, and you also plan to use the above method to get the position, then consider storing the keys in a List instead, since the lookup time will be the same, and List order is guaranteed to be preserved.


Dictionaries have no implied order of key-value pairs. If you need the "position," you are using them the wrong way.

On your edit: If you are implementing a matrix, your best bet would be to use a multidimensional array. Eg:

int[,] matrix = new int[3, 2] { {1, 2}, {3, 4}, {5, 6} };

Is equivalent to a matrix like:

1 2
3 4
5 6

You can access its elements using matrix[i][j]; eg matrix[0][0] is 1, matrix[0][1] is 2, etc.


You will not be able to use any of the builtin collection data structures including KeyedCollection. However, you can easily make your own collection class by deriving from Collection and which contains a Dictionary internally for quick lookups on the key. The Collection class itself provides the ability for indexed retrieval.

public class KeyValueCollection<TKey, TValue> : Collection<KeyValuePair<TKey, TValue>>
{
    private Dictionary<TKey, TValue> m_Dictionary = new Dictionary<TKey, TValue>();

    public TValue GetValue(TKey key)
    {
        return m_Dictionary[key];
    }

    public void Add(TKey key, TValue value)
    {
        m_Dictionary.Add(key, value);
        base.Add(new KeyValuePair<TKey, TValue>(key, value));
    }

    protected override void ClearItems()
    {
        m_Dictionary.Clear();
        base.ClearItems();
    }

    protected override void InsertItem(int index, KeyValuePair<TKey, TValue> item)
    {
        m_Dictionary.Add(item.Key, item.Value);
        base.InsertItem(index, item);
    }

    protected override void RemoveItem(int index)
    {

        m_Dictionary.Remove(this[index].Key);
        base.RemoveItem(index);
    }

    protected override void SetItem(int index, KeyValuePair<TKey, TValue> item)
    {
        m_Dictionary[this[index].Key] = item.Value;
        base.SetItem(index, item);
    }
}


If you are really looking for that functionality, why don't you maintain an auxilary data structure which maintains the order in which you added the elements

(OR)

Probably you want to just maintain a List of Structures which store

   [{"a",-1},{"b",1},{"c",0},{"d",-1},{"e",-9}]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜