I've been trying to write an extension method to mimic List.RemoveAll(Predicate).
So far I've got this:
public static void RemoveAll<TKey,TValue>(this Dictionary<TKey,TValue> dict,
Predicate<KeyValuePair<TKey,TValue>> condition)
{
Dictionary<TKey,TValue> temp = new Dictionary<TKey,TValue>();
foreach (var item in dict)
{
if (!condition.Invoke(item))
temp.Add(item.Key, item.Value);
}
dict = temp;
}
Any pointers? Is this a completely naive implementation?
NET 4.0 and is available in the System. Collections. Concurrent namespace. It is thread-safe and internally uses locking.
The Dictionary<TKey, TValue> Class in C# is a collection of Keys and Values. It is a generic collection class in the System. Collections. Generic namespace. The Dictionary <TKey, TValue> generic class provides a mapping from a set of keys to a set of values.
In C#, Dictionary is a generic collection which is generally used to store key/value pairs. The working of Dictionary is quite similar to the non-generic hashtable. The advantage of Dictionary is, it is generic type. Dictionary is defined under System.
Your code will not work because you are passing the Dictionary class by value. This means the final assignment (dict = temp) will not be visible to a calling function. It is not legal in C# to pass extension method targets by ref or out (in VB it's legal to do ByRef).
Instead you will need to modify the Dictionary inline. Try the following
public static void RemoveAll<TKey,TValue>(this Dictionary<TKey,TValue> dict,
Func<KeyValuePair<TKey,TValue>,bool> condition)
{
foreach ( var cur in dict.Where(condition).ToList() ) {
dict.Remove(cur.Key);
}
}
EDIT
Swapped the order of Where and ToList to reduce the size of the allocated memory of the list. It will now only allocate a list for the items that are to be removed.
public static void RemoveAll<TKey,TValue>(
this Dictionary<TKey,TValue> dict,
Predicate<KeyValuePair<TKey,TValue>> condition)
{
var toRemove = new List<TKey>();
foreach (var item in dict)
{
if (!condition(item))
toRemove.Add(item);
}
foreach (var key in toRemove)
{
dict.Remove(key);
}
}
If the number of keys to remove is small relative to the dictionary size this will be faster (if the number removed is likely to be zero you can make this even faster by lazily creating the toRemove list as well.
This boils down to the same as Jared's updated answer but allows you to defer the creation of the removal list if you so desire. If this is not an issue (and you have no reason to break point part way through the process) then Jared's is cleaner and simpler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With