Extension methods Dictionary <TKey, TValue> .RemoveAll? Is it possible?

I am trying to write an extension method to simulate List.RemoveAll (Predicate).

So far I have 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?

+7
generics extension-methods
source share
4 answers

Your code will not work because you are passing a Dictionary class by value. This means that the final assignment (dict = temp) will not be displayed to the calling function. In C #, it is not allowed to pass the goals of an extension method using ref or out (in VB, ByRef is legal to do this).

Instead, you will need to change the dictionary in the line. 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

Changed the order of Where and ToList to reduce the size of the allocated list memory. Now it will highlight the list only for items that need to be removed.

+16
source share
 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 delete is small relative to the size of the dictionary, this will be faster (if the number of deleted keys is likely to be zero, you can do it even faster by lazily creating a toRemove list.

It comes down to the same thing as Jared, but allows you to defer the creation of the deletion list if you wish. If this is not a problem (and you have no reason to interrupt the process of a partial part of the process), then Jared is cleaner and simpler.

+4
source share

This method will not work because the "dict" parameter is not passed by reference, and in fact it cannot be because ref is not supported as the first parameter of the extension method.

 public static void RemoveAll<TKey,TValue>(this Dictionary<TKey,TValue> dict, Predicate<KeyValuePair<TKey,TValue>> condition) { var temp = new List<TKey>(); foreach (var item in dict) { if (!condition(item)) temp.Add(item.Key); } foreach (var itemKey in temp) dict.Remove(itemKey) } 

I would also like to see implementations of RemoveAllByKey and RemoveAllByValue.

+1
source share

But if you wanted, you could return a new and different Dictionary. Your signature will change to this:

 public static Dictionary<TKey, TValue> RemoveAll<TKey,TValue>(this Dictionary<TKey,TValue> dict, Predicate<KeyValuePair<TKey,TValue>> condition) 

And the calling code would say:

 var newDict = oldDict.RemoveAll(kvp=> kvp.Name.StartsWith("something")); 

And if you want to change oldDict, you would call it the following:

 oldDict = oldDict.RemoveAll(kvp=> kvp.Name.StartsWith("something")); 
0
source share

All Articles