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我同意,它确实不是一个问题