Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 按键从字典中删除并检索值_C#_.net_Dictionary - Fatal编程技术网

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

C# 按键从字典中删除并检索值,c#,.net,dictionary,C#,.net,Dictionary,是否有方法从字典中删除条目(通过键)并在“同一步骤”中检索其值 例如,我正在打电话 Dictionary.Remove(Key); 但我也希望同时返回值。该函数仅返回一个bool 我知道我可以做像这样的事情 Value = Dictionary[Key]; Dictionary.Remove(Key); 但这似乎会搜索字典两次(一次获取值,另一次从字典中删除)。如果可能的话,如何在不搜索字典两次的情况下同时执行这两项操作?您可以使用扩展方法: public static string Get

是否有方法从
字典中删除条目(通过
)并在“同一步骤”中检索其

例如,我正在打电话

Dictionary.Remove(Key);
但我也希望同时返回值。该函数仅返回一个
bool

我知道我可以做像这样的事情

Value = Dictionary[Key];
Dictionary.Remove(Key);

但这似乎会搜索字典两次(一次获取值,另一次从字典中删除)。如果可能的话,如何在不搜索字典两次的情况下同时执行这两项操作?

您可以使用扩展方法:

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);
}
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);
}
公共静态字符串GetValueAndRemove(此字典dict dict,int键)
{
字符串val=dict[key];
删除指令(键);
返回val;
}
静态void Main(字符串[]参数)
{
字典a=新字典();
a、 添加(1,“sdfg”);
a、 添加(2,“SDFGADFHFG”);
字符串值=a.GetValueAndRemove(1);
}

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

public class PoppableDictionary<T, V> : Dictionary<T, V>
{
    public V Pop(T key)
    {
        V value = this[key];
        this.Remove(key);
        return value;
    }
}
公共类PoppableDictionary:字典
{
公共V键(T键)
{
V值=此[键];
这个。移除(键);
返回值;
}
}

尽管这不是OP要求的,但我还是忍不住发布了一个正确的扩展方法:

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);
}
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);
}
public static bool Remove(此字典自身、TKey、out TValue目标)
{
self.TryGetValue(键,输出目标);
返回自我。移除(键);
}

< /代码> 因为它们都有所需的缺失方法,所以我尝试了哥本哈根大学的微软和C5,我可以告诉他们,至少在我的用例中,它比字典慢得多(我的意思是5x-10x慢)。 我认为C5一直在对键和值进行排序,并发字典“太担心”调用线程。。我在这里不是要讨论字典的这两个化身为何如此缓慢。 我的算法是寻找和替换一些条目,而第一个密钥将被删除,新的密钥将被添加(某种队列)。。。 剩下要做的唯一一件事就是修改原始的.Net mscorelib字典。我从Microsoft下载了源代码,并将该类包含在源代码中。为了编译,我还需要拖拽类和类。剩下的就是注释掉一些行(例如,
[DebuggerTypeProxy(typeof(Mscorlib\u DictionaryDebugView))]
和一些资源获取)。显然,我必须将缺少的方法添加到复制的类中。也不要试图编译微软的源代码,你将在几个小时内完成这项工作,我很幸运地完成了这项工作

   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;
    }
public bool Remove(TKey键,out TValue值)
{
if(key==null)
{
ThrowHelper.ThrowArgumentNullException(argument.key除外);
}
if(bucket!=null)
{
int hashCode=comparer.GetHashCode(键)&0x7FFFFFFF;
int bucket=hashCode%bucket.Length;
int last=-1;
for(int i=bucket[bucket];i>=0;last=i,i=entries[i]。下一步)
{
if(条目[i].hashCode==hashCode&&comparer.Equals(条目[i].key,key))
{
如果(最后一次<0)
{
bucket[bucket]=条目[i]。下一步;
}
其他的
{
条目[last].next=条目[i].next;
}
条目[i]。hashCode=-1;
条目[i]。下一步=自由列表;
条目[i].key=默认值(TKey);
值=条目[i]。值;
条目[i]。值=默认值(TValue);
自由列表=i;
freeCount++;
版本++;
返回true;
}
}
}
值=默认值(TValue);
返回false;
}
最后,我将名称空间修改为
System.Collection.Generic.My
在我的算法中,我只得到了两行值,然后在下一行中删除。。用新方法代替了该方法,获得了7%-10%的稳定性能增益。
希望它能帮助这个用例和任何其他从头开始重新实现Dictionary的情况。

concurrentDictionary
有一个
TryRemove
方法,该方法尝试从
System.Collections.Concurrent.ConcurrentDictionary.
如果键不存在,则返回
TValue
类型的默认值


从.NET Core 2.0开始,我们有:

公共bool Remove(TKey键,out TValue值)


请注意,此API尚未包括在内。

此线程的可能副本有一个公认的答案。如果它也与性能相关,您可以在此处查看答案,看看这是否清除了任何内容up@Kenneth:所以,我想这不能用“内置”来完成.NET中的字典类型?@Mash:假设您的
缓存或计算散列代码,则双重查找的性能开销很小。大多数字典都有O(1)查找和删除功能。好吧,没有,但既然这是一个显而易见的合法要求,我想一定有人问过。我想唯一可能的方法是实现你自己的字典。不是要批评,但我怀疑它是否会更快:)既然删除是安全的,我建议先检查密钥是否存在,但无论如何是个好主意:)谢谢你的回答,但我应该更清楚地说“在同一步”。我真正的意思是不要搜索字典两次。
string val=dict[key]
将搜索字典一次,而
dict.Remove(key)
将再次搜索。@Mash字典速度非常快,所以性能方面应该不会有大问题。@Silvermind我同意,它确实不是一个问题