Is there a way to use .ForEach on Dictionary contents? - c#

I changed a collection from List to Dictionary and it seems I need change from using .ForEach() to foreach() on it - regardless if I'm iterating the Dictionary itself, or Dictionary.Values.
It's no big deal but I've seen a few times slight discrepancies when you can and can't use LINQ, and I wondered if there is a way and I just missed it?

Unfortunately .ForEach() is only defined on the List<> class.
You could either use .ToList() first to get access to .ForEach but that will, of course, lower the performance compared to just using foreach or you could create extension-methods for that:
public static void ForEach<T, U>(this Dictionary<T, U> d, Action<KeyValuePair<T, U>> a)
{
foreach (KeyValuePair<T, U> p in d) { a(p); }
}
public static void ForEach<T, U>(this Dictionary<T, U>.KeyCollection k, Action<T> a)
{
foreach (T t in k) { a(t); }
}
public static void ForEach<T, U>(this Dictionary<T, U>.ValueCollection v, Action<U> a)
{
foreach (U u in v) { a(u); }
}
If you are interested in further information, there is already a similar article on SO.

Related

C# compare lists List<T>

using Microsoft.VisualStudio.TestTools.UnitTesting;
I want universal test method, which gets Dictionary and function, and then check equality for each dictionary entry between Value and function(Key):
public void TestMethod<TKey, TValue>(Dictionary<TKey, TValue> dict, Func<TKey, TValue> func)
{
foreach (var test in dict)
{
Assert.AreEqual(test.Value, func(test.Key));
}
}
But if Values (and return value of function) is
List<int>
it doesnt work, of course. So, I found than I need
CollectionAssert.AreEqual
for such cases.
But now I have to say, that my value is System.Collections.ICollection. How to do this?
You need to cast the values to ICollection so the compiler won't complain.
public void TestMethod<TKey, TValue>(Dictionary<TKey, TValue> dict, Func<TKey, TValue> func)
{
foreach (var test in dict)
{
if (test.Value is ICollection)
{
CollectionAssert.AreEqual((ICollection)test.Value, (ICollection)func(test.Key));
}
else
{
Assert.AreEqual(test.Value, func(test.Key));
}
}
}

In LINQ, how do I modify an existing LINQ extension method to add a "By" selector, i.e. add Func<T> TResult to the function signature?

I am very curious to know how to modify an existing LINQ function to add Func<T> TResult to the function signature, i.e. allow it to use a selector as in (o => o.CustomField).
For example, in C#, I can use .IsDistinct() to check if a list of integers are distinct. I can also use .IsDistinctBy(o => o.SomeField) to check if the integers in field o.SomeField are distinct. I believe that, behind the scenes, .IsDistinctBy(...) has something like the function signature Func<T> TResult appended to it?
My question is this: what is the technique for taking an existing LINQ extension function, and converting it so it can have a parameter (o => o.SomeField)?
Here is an example.
This extension function checks to see if a list is increasing monotonically (i.e. values are never decreasing, as in 1,1,2,3,4,5,5):
main()
{
var MyList = new List<int>() {1,1,2,3,4,5,5};
DebugAssert(MyList.MyIsIncreasingMonotonically() == true);
}
public static bool MyIsIncreasingMonotonically<T>(this List<T> list) where T : IComparable
{
return list.Zip(list.Skip(1), (a, b) => a.CompareTo(b) <= 0).All(b => b);
}
If I want to add a "By", I add a parameter Func<T> TResult. But how do I modify the body of the function to make it select by (o => o.SomeField)?
main()
{
DebugAssert(MyList.MyIsIncreasingMonotonicallyBy(o => o.CustomField) == true);
}
public static bool MyIsIncreasingMonotonicallyBy<T>(this List<T> list, Func<T> TResult) where T : IComparable
{
// Question: How do I modify this function to make it
// select by o => o.CustomField?
return list.Zip(list.Skip(1), (a, b) => a.CompareTo(b) <= 0).All(b => b);
}
Consider an implementation like the following, which enumerates the given IEnumerable<T> only once. Enumerating can have side-effects, and callers typically expect a single pass-through if that's possible.
public static bool IsIncreasingMonotonically<T>(
this IEnumerable<T> _this)
where T : IComparable<T>
{
using (var e = _this.GetEnumerator())
{
if (!e.MoveNext())
return true;
T prev = e.Current;
while (e.MoveNext())
{
if (prev.CompareTo(e.Current) > 0)
return false;
prev = e.Current;
}
return true;
}
}
Your enumerable.IsIncreasingMonotonicallyBy(x => x.MyProperty) overload that you describe can now be written as follows.
public static bool IsIncreasingMonotonicallyBy<T, TKey>(
this IEnumerable<T> _this,
Func<T, TKey> keySelector)
where TKey : IComparable<TKey>
{
return _this.Select(keySelector).IsIncreasingMonotonically();
}
Just apply the Func to a and b:
public static bool MyIsIncreasingMonotonicallyBy<T, TResult>(this IEnumerable<T> list, Func<T, TResult> selector)
where TResult : IComparable<TResult>
{
return list.Zip(list.Skip(1), (a, b) => selector(a).CompareTo(selector(b)) <= 0).All(b => b);
}
One above is close to right but there are issues:
Your list has possible multiple enumeration of IEnumeration
public static bool MyIsIncreasingMonotonicallyBy<T, TResult>(
this IEnumerable<T> list, Func<T, TResult> selector)
where TResult : IComparable<TResult>
{
var enumerable = list as IList<T> ?? list.ToList();
return enumerable.Zip(
enumerable.Skip(1),
(a, b) => selector(a).CompareTo(selector(b)) <= 0
).All(b => b);
}
P.S. I believe you need to remove the "this" because Extension method can only be declared in non-generic, non-nested static class.
In response to Frédéric Hamidi:
Consider the following:
IEnumerable<string> names = GetNames();
foreach (var name in names) Console.WriteLine("Found " + name);
var allNames = new StringBuilder();
foreach (var name in names) allNames.Append(name + " ");
Assuming that GetNames() returns an IEnumerable, we are, effectively, doing extra work by enumerating this collection twice in the two foreach statements. If GetNames() results in a database query, you end up doing that query twice, while both times getting the same data.
This kind of problem can be easily fixed – simply force the enumeration at the point of variable initialization by converting the sequence to a list(or you could do array). Both array and list types implement the IEnumerable interface.

Lookup extension method

Rather than create a whole new class implementing ILookup<T> is it possible to add an extension method to dictionary which caters for it? I'm thinking something along the following:
public static void LookupAdd(this Dictionary<T, List<V>> dict, T key, V item)
{
if (!dict.ContainsKey(key))
{
dict.Add(key, new List<T>());
}
dict[key].Add(item);
}
This fails to compile saying it can't identify the types. I'm guessing that my generic parameters are too complex (particularly List<V>)
You have forgotten to add the generic parameter syntax:
public static void LookupAdd<T, V>(this Dictionary<T, List<V>> dictionary, T key, V item)
{
}
The <T, V> is missing.
Try...
public static void LookupAdd<T,V>(this Dictionary<T, List<V>> dict, T key, V item)
{
if (!dict.ContainsKey(key))
{
dict.Add(key, new List<V>());
}
dict[key].Add(item);
}
UPDATE:
Notice that you should have
new List<V>()
where you have
new List<T>()

Best way to remove multiple items matching a predicate from a .NET Dictionary?

I need to remove multiple items from a Dictionary.
A simple way to do that is as follows :
List<string> keystoremove= new List<string>();
foreach (KeyValuePair<string,object> k in MyCollection)
if (k.Value.Member==foo)
keystoremove.Add(k.Key);
foreach (string s in keystoremove)
MyCollection.Remove(s);
The reason why I can't directly Remove the items in the foreach block is that this would throw an Exception ("Collection was modified...")
I'd like to do the following :
MyCollection.RemoveAll(x =>x.Member==foo)
But the Dictionary<> class doesn't expose a RemoveAll(Predicate<> Match) method, like the List<> Class does.
What's the best way (both performance wise and elegant wise) to do that?
Here's an alternate way
foreach ( var s in MyCollection.Where(kv => kv.Value.Member == foo).ToList() ) {
MyCollection.Remove(s.Key);
}
Pushing the code into a list directly allows you to avoid the "removing while enumerating" problem. The .ToList() will force the enumeration before the foreach really starts.
you can create an extension method:
public static class DictionaryExtensions
{
public static void RemoveAll<TKey, TValue>(this IDictionary<TKey, TValue> dict,
Func<TValue, bool> predicate)
{
var keys = dict.Keys.Where(k => predicate(dict[k])).ToList();
foreach (var key in keys)
{
dict.Remove(key);
}
}
}
...
dictionary.RemoveAll(x => x.Member == foo);
Instead of removing, just do the inverse. Create a new dictionary from the old one containing only the elements you are interested in.
public Dictionary<T, U> NewDictionaryFiltered<T, U>
(
Dictionary<T, U> source,
Func<T, U, bool> filter
)
{
return source
.Where(x => filter(x.Key, x.Value))
.ToDictionary(x => x.Key, x => x.Value);
}
Modified version of Aku's extension method solution. Main difference is that it allows the predicate to use the dictionary key. A minor difference is that it extends IDictionary rather than Dictionary.
public static class DictionaryExtensions
{
public static void RemoveAll<TKey, TValue>(this IDictionary<TKey, TValue> dic,
Func<TKey, TValue, bool> predicate)
{
var keys = dic.Keys.Where(k => predicate(k, dic[k])).ToList();
foreach (var key in keys)
{
dic.Remove(key);
}
}
}
. . .
dictionary.RemoveAll((k,v) => v.Member == foo);
Starting from the .NET 3.0, it's now allowed to remove items from a Dictionary<TKey,TValue> while enumerating it. According to the documentation:
.NET Core 3.0+ only: The only mutating methods which do not invalidate enumerators are Remove and Clear.
Here is the GitHub issue where this change was proposed and approved: Allow Dictionary<K,V>.Remove during enumeration
So the RemoveAll extension method can be implemented simply like this:
/// <remarks>.NET Core 3.0+ only.</remarks>
public static void RemoveAll<TKey, TValue>(this Dictionary<TKey, TValue> source,
Predicate<KeyValuePair<TKey, TValue>> predicate)
{
foreach (var pair in source)
if (predicate(pair))
source.Remove(pair.Key);
}
Usage example:
myDictionary.RemoveAll(e => e.Value.Member == foo);
The fastest way to remove would be either:
public static void RemoveAll<TKey, TValue>(this IDictionary<TKey, TValue> idict, Func<KeyValuePair<TKey, TValue>, bool> predicate)
{
foreach (var kvp in idict.Where(predicate).ToList())
{
idict.Remove(kvp.Key);
}
}
or
public static void RemoveAll<T>(this ICollection<T> icollection, Predicate<T> predicate)
{
var nonMatchingItems = new List<T>();
// Move all the items that do not match to another collection.
foreach (var item in icollection)
{
if (!predicate(item))
{
nonMatchingItems.Add(item);
}
}
// Clear the collection and then copy back the non-matched items.
icollection.Clear();
foreach (var item in nonMatchingItems)
{
icollection.Add(item);
}
}
depending on whether you have more cases of predicate returning true or not. Both are O(N) in nature, but 1st approach will be faster if you have very less cases of "removal/lookup", and the second one faster if items in collection matches the condition majority of the times.
Can you just change your loop to use an index (i.e. FOR instead of FOREACH)? You'd have to loop backwards, of course, i.e. count-1 down to zero.
Instead of removing just do the inverse (create a new dictionary from the old one containing only the elements you are interested in) and let the garbage collector take care of the old dictionary:
var newDictionary = oldDictionary.Where(x => x.Value != foo);
It's simple using LINQ. Just do the following :)
MyCollection = MyCollection.Where(mc => !keystoremove.Contains(mc.Key))
.ToDictionary(d => d.Key, d => d.Value);

Generic Map/Reduce List Extensions in C#

I am writing a few extensions to mimic the map and reduce functions in Lisp.
public delegate R ReduceFunction<T,R>(T t, R previous);
public delegate void TransformFunction<T>(T t, params object[] args);
public static R Reduce<T,R>(this List<T> list, ReduceFunction<T,R> r, R initial)
{
var aggregate = initial;
foreach(var t in list)
aggregate = r(t,aggregate);
return aggregate;
}
public static void Transform<T>(this List<T> list, TransformFunction<T> f, params object [] args)
{
foreach(var t in list)
f(t,args);
}
The transform function will cut down on cruft like:
foreach(var t in list)
if(conditions && moreconditions)
//do work etc
Does this make sense? Could it be better?
According to this link Functional Programming in C# 3.0: How Map/Reduce/Filter can Rock your World the following are the equivalent in C# under the System.Linq namespace:
map --> Enumerable.Select
reduce --> Enumerable.Aggregate
filter --> Enumerable.Where
These look very similar to extensions in Linq already:
//takes a function that matches the Func<T,R> delegate
listInstance.Aggregate(
startingValue,
(x, y) => /* aggregate two subsequent values */ );
//takes a function that matches the Action<T> delegate
listInstance.ForEach(
x => /* do something with x */);
Why is the 2nd example called Transform? Do you intend to change the values in the list somehow? If that's the case you may be better off using ConvertAll<T> or Select<T>.
I would use the built in Func delegates instead. This same code would work on any IEnumerable. Your code would turn into:
public static R Reduce<T,R>(this IEnumerable<T> list, Func<T,R> r, R initial)
{
var aggregate = initial;
foreach(var t in list)
aggregate = r(t,aggregate);
return aggregate;
}
public static void Transform<T>(this IEnumerable<T> list, Func<T> f)
{
foreach(var t in list)
f(t);
}
You might want to add a way to do a map but return a new list, instead of working on the list passed in (and returning the list can prove useful to chain other operations)... perhaps an overloaded version with a boolean that indicates if you want to return a new list or not, as such:
public static List<T> Transform<T>(this List<T> list, TransformFunction<T> f,
params object [] args)
{
return Transform(list, f, false, args);
}
public static List<T> Transform<T>(this List<T> list, TransformFunction<T> f,
bool create, params object [] args)
{
// Add code to create if create is true (sorry,
// too lazy to actually code this up)
foreach(var t in list)
f(t,args);
return list;
}
I would recommend to create extension methods that internally use LinQ like this:
public static IEnumerable<R> Map<T, R>(this IEnumerable<T> self, Func<T, R> selector) {
return self.Select(selector);
}
public static T Reduce<T>(this IEnumerable<T> self, Func<T, T, T> func) {
return self.Aggregate(func);
}
public static IEnumerable<T> Filter<T>(this IEnumerable<T> self, Func<T, bool> predicate) {
return self.Where(predicate);
}
Here some example usages:
IEnumerable<string> myStrings = new List<string>() { "1", "2", "3", "4", "5" };
IEnumerable<int> convertedToInts = myStrings.Map(s => int.Parse(s));
IEnumerable<int> filteredInts = convertedToInts.Filter(i => i <= 3); // Keep 1,2,3
int sumOfAllInts = filteredInts.Reduce((sum, i) => sum + i); // Sum up all ints
Assert.Equal(6, sumOfAllInts); // 1+2+3 is 6
(See https://github.com/cs-util-com/cscore#ienumerable-extensions for more examples)

Categories

Resources