按键从字典中删除并检索值

时间:2013-04-15 23:16:38

标签: c# .net dictionary

有没有办法从Dictionary删除条目(Key)并在“同一步骤”中检索Value

例如,我正在打电话

Dictionary.Remove(Key);

但我也希望同时返回Value。该函数仅返回bool

我知道我可以做类似

的事情
Value = Dictionary[Key];
Dictionary.Remove(Key);

但似乎这会搜索字典两次(一次获取值,另一次将其从字典中删除)。我怎么能(如果可能的话)两次都没有搜索字典?

6 个答案:

答案 0 :(得分:3)

答案 1 :(得分:2)

因为他们都有所需的遗漏方法,我尝试了来自哥本哈根大学ConcurrentDictionary的微软http://www.itu.dk/research/c5/和C5,我可以告诉他,至少我的用例是超级慢(比起字典,我的意思是慢5倍 - 10倍)。 我认为C5一直在对键和值进行排序,并且“并发字典”过于担心&#34;关于调用线程..我不是在这里讨论为什么这两个字典的化身很慢。 我的算法正在寻找和替换一些条目,而第一个键将被删除,新的密钥将被添加(某种类型的队列)... 剩下的唯一想法是修改原始.Net mscorelib的词典。我从Microsoft下载了源代码,并在我的源代码中包含了Dictionary类。要编译我还需要拖动HashHelpers类和ThrowHelper类。剩下的就是注释掉一些行(例如[DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<,>))]和一些资源提取)。显然我必须将复制的类添加到缺少的方法中。另外,不要尝试编译Microsoft源代码,您将在几个小时内完成这项工作,我很幸运能够实现它。

   public bool Remove(TKey key, out TValue value)
    {
        if (key == null)
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
        }

        if (buckets != null)
        {
            int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
            int bucket = hashCode % buckets.Length;
            int last = -1;
            for (int i = buckets[bucket]; i >= 0; last = i, i = entries[i].next)
            {
                if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key))
                {
                    if (last < 0)
                    {
                        buckets[bucket] = entries[i].next;
                    }
                    else
                    {
                        entries[last].next = entries[i].next;
                    }
                    entries[i].hashCode = -1;
                    entries[i].next = freeList;
                    entries[i].key = default(TKey);
                    value = entries[i].value;
                    entries[i].value = default(TValue);
                    freeList = i;
                    freeCount++;
                    version++;
                    return true;
                }
            }
        }
        value = default(TValue);
        return false;
    }

最后我将命名空间修改为System.Collection.Generic.My 在我的算法中,我只有两行我获得的值而不是在下一行中删除它。用 new 方法替换它并获得7%-10%的稳定性能增益。 希望它有助于这个用例以及从头开始重新实现Dictionary的任何其他情况,而不是人们应该做的事情。

答案 2 :(得分:1)

即使这不是OP所要求的,我也无法帮助自己,但发布了更正的扩展方法:

public static bool Remove<TKey, TValue>(this Dictionary<TKey, TValue> self, TKey key, out TValue target)
{
    self.TryGetValue(key, out target);
    return self.Remove(key);
}

答案 3 :(得分:1)

concurrentDictionary有一个TryRemove方法,尝试从System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>.中删除并返回具有指定键的值 如果密钥不存在,则返回TValue类型的默认值。

https://msdn.microsoft.com/en-us/library/dd287129(v=vs.110).aspx

答案 4 :(得分:-1)

您可以使用Extension方法执行此操作:

public static string GetValueAndRemove<TKey, TValue>(this Dictionary<int, string> dict, int key)
{
    string val = dict[key];
    dict.Remove(key);
    return val;    
}

static void Main(string[] args)
{
    Dictionary<int, string> a = new Dictionary<int, string>();
    a.Add(1, "sdfg");
    a.Add(2, "sdsdfgadfhfg");
    string value = a.GetValueAndRemove<int, string>(1);
}

答案 5 :(得分:-1)

您可以扩展该类以添加该功能:

public class PoppableDictionary<T, V> : Dictionary<T, V>
{
    public V Pop(T key)
    {
        V value = this[key];
        this.Remove(key);
        return value;
    }
}