Accessing a Dictionary.Keys Key through a numeric index

前端 未结 15 1176
失恋的感觉
失恋的感觉 2020-12-07 13:49

I\'m using a Dictionary where the int is a count of the key.

Now, I need to access the last-inserted Key inside the Dict

相关标签:
15条回答
  • 2020-12-07 14:00

    I think you can do something like this, the syntax might be wrong, havent used C# in a while To get the last item

    Dictionary<string, int>.KeyCollection keys = mydict.keys;
    string lastKey = keys.Last();
    

    or use Max instead of Last to get the max value, I dont know which one fits your code better.

    0 讨论(0)
  • 2020-12-07 14:02

    One alternative would be a KeyedCollection if the key is embedded in the value.

    Just create a basic implementation in a sealed class to use.

    So to replace Dictionary<string, int> (which isn't a very good example as there isn't a clear key for a int).

    private sealed class IntDictionary : KeyedCollection<string, int>
    {
        protected override string GetKeyForItem(int item)
        {
            // The example works better when the value contains the key. It falls down a bit for a dictionary of ints.
            return item.ToString();
        }
    }
    
    KeyedCollection<string, int> intCollection = new ClassThatContainsSealedImplementation.IntDictionary();
    
    intCollection.Add(7);
    
    int valueByIndex = intCollection[0];
    
    0 讨论(0)
  • 2020-12-07 14:03

    In case you decide to use dangerous code that is subject to breakage, this extension function will fetch a key from a Dictionary<K,V> according to its internal indexing (which for Mono and .NET currently appears to be in the same order as you get by enumerating the Keys property).

    It is much preferable to use Linq: dict.Keys.ElementAt(i), but that function will iterate O(N); the following is O(1) but with a reflection performance penalty.

    using System;
    using System.Collections.Generic;
    using System.Reflection;
    
    public static class Extensions
    {
        public static TKey KeyByIndex<TKey,TValue>(this Dictionary<TKey, TValue> dict, int idx)
        {
            Type type = typeof(Dictionary<TKey, TValue>);
            FieldInfo info = type.GetField("entries", BindingFlags.NonPublic | BindingFlags.Instance);
            if (info != null)
            {
                // .NET
                Object element = ((Array)info.GetValue(dict)).GetValue(idx);
                return (TKey)element.GetType().GetField("key", BindingFlags.Public | BindingFlags.Instance).GetValue(element);
            }
            // Mono:
            info = type.GetField("keySlots", BindingFlags.NonPublic | BindingFlags.Instance);
            return (TKey)((Array)info.GetValue(dict)).GetValue(idx);
        }
    };
    
    0 讨论(0)
  • 2020-12-07 14:03

    To expand on Daniels post and his comments regarding the key, since the key is embedded within the value anyway, you could resort to using a KeyValuePair<TKey, TValue> as the value. The main reasoning for this is that, in general, the Key isn't necessarily directly derivable from the value.

    Then it'd look like this:

    public sealed class CustomDictionary<TKey, TValue>
      : KeyedCollection<TKey, KeyValuePair<TKey, TValue>>
    {
      protected override TKey GetKeyForItem(KeyValuePair<TKey, TValue> item)
      {
        return item.Key;
      }
    }
    

    To use this as in the previous example, you'd do:

    CustomDictionary<string, int> custDict = new CustomDictionary<string, int>();
    
    custDict.Add(new KeyValuePair<string, int>("key", 7));
    
    int valueByIndex = custDict[0].Value;
    int valueByKey = custDict["key"].Value;
    string keyByIndex = custDict[0].Key;
    
    0 讨论(0)
  • 2020-12-07 14:06

    Why don't you just extend the dictionary class to add in a last key inserted property. Something like the following maybe?

    public class ExtendedDictionary : Dictionary<string, int>
    {
        private int lastKeyInserted = -1;
    
        public int LastKeyInserted
        {
            get { return lastKeyInserted; }
            set { lastKeyInserted = value; }
        }
    
        public void AddNew(string s, int i)
        {
            lastKeyInserted = i;
    
            base.Add(s, i);
        }
    }
    
    0 讨论(0)
  • 2020-12-07 14:08

    You could always do this:

    string[] temp = new string[mydict.count];
    mydict.Keys.CopyTo(temp, 0)
    int LastCount = mydict[temp[mydict.count - 1]]
    

    But I wouldn't recommend it. There's no guarantee that the last inserted key will be at the end of the array. The ordering for Keys on MSDN is unspecified, and subject to change. In my very brief test, it does seem to be in order of insertion, but you'd be better off building in proper bookkeeping like a stack--as you suggest (though I don't see the need of a struct based on your other statements)--or single variable cache if you just need to know the latest key.

    0 讨论(0)
提交回复
热议问题