Generic Map/Reduce List Extensions in C# - 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)

Related

Dynamic LINQ Method to return List of different Items from two lists

I want to write dynamic LINQ function to return the different between two lists but in abstraction way to make this function take any two lists of the same type and return the items that is the first list but not in the second one
I write some thing like the below and it is working fine but as I mention above I need it in abstraction way
List<Employee> a = List of Items;
List<Employee> b = List of Items;
var finalCountries = a.Where(u => !b.Any(u2 => u2.ISOA2 == u.ISOA2)).ToList();
I read about dynamic LINQ expression but it is complex and I have no luck to find what I am looking to
if there are any way to write the above where statement as string and execute it?
You can use Enumerable.Except like this
List<Employee> a;
List<Employee> b;
var finalCountries = a.Except(b).ToList();
If you need to compare your Employees by some field and this is not implemented by Employee you can use a custom comparer. For example this one. When your code can look like:
var comparer = new LambdaComparer<Employee>((emp1,emp2)=>emp1.ISOA2 == emp2.ISOA2);
var finalCountries = a.Except(b,comparer).ToList();
LambdaComparer code for convenience:
class LambdaComparer<T> : IEqualityComparer<T>
{
readonly Func<T, T, bool> _lambdaComparer;
readonly Func<T, int> _lambdaHash;
public LambdaComparer(Func<T, T, bool> lambdaComparer) :
this(lambdaComparer, o => 0){}
public LambdaComparer(Func<T, T, bool> lambdaComparer, Func<T, int> lambdaHash)
{
_lambdaComparer = lambdaComparer ?? throw new ArgumentNullException(nameof(lambdaComparer));
_lambdaHash = lambdaHash ?? throw new ArgumentNullException(nameof(lambdaHash));
}
public bool Equals(T x, T y) => _lambdaComparer(x, y);
public int GetHashCode(T obj) => _lambdaHash(obj);
}
update:
To make your method generic you can implement IEquatable interface in each of your entity types and use Except overload without parameters.

Making Objects that Don't Inherit from IEnumerable<> Queryable via LINQ

I have a class called IDCollection which is not actually a List<>, Dictionary<,>, or similar IEnumerable-based type. Though it does have an indexer, it's based on a private Dictionary<string, ID> called innerList, so objects of the class themselves are not lists, nor does it hold key value pairs or a collection of items through its own this accessor.
Is it possible to make an IDCollection object queryable in a LINQ expression? If so, how?
For example, suppose the object is called testIdColl. In that case...
from KeyValuePair<string, ID> k in testIDColl
select k;
etc.
And is the IQueryable interface involved at all?
This is all you would need to do to your class:
public class IDCollection : IEnumerable<KeyValuePair<string, ID>>
{
private IDictionary<string, ID> List = new Dictionary<string, ID>();
public IEnumerator<KeyValuePair<string, ID>> GetEnumerator()
{
return List.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Then you could run this code:
var testIDColl = new IDCollection();
var query =
from KeyValuePair<string, ID> k in testIDColl
select k;
If you want you could make the entire IEnumerable<...> interface private like so:
public class IDCollection : IEnumerable<KeyValuePair<string, ID>>
{
private IDictionary<string, ID> List = new Dictionary<string, ID>();
IEnumerator<KeyValuePair<string, ID>> IEnumerable<KeyValuePair<string, ID>>.GetEnumerator()
{
return List.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return List.GetEnumerator();
}
}
Now nothing is directly exposed.
I created an implementation of the three instance methods from Jakub's answer:
public class IDCollection
{
private IDictionary<string, ID> List = new Dictionary<string, ID>() { { "x", new ID() }, } ;
public IEnumerable<KeyValuePair<string, ID>> Where(Func<KeyValuePair<string, ID>, bool> selector)
{
return List.Where(selector);
}
public IEnumerable<TResult> Select<TResult>(Func<KeyValuePair<string, ID>, TResult> selector)
{
return List.Select(selector);
}
}
The Cast method was not needed to perform basic queries.
I would suggest adding an explicit AsEnumerable() method instead to expose the full range of LINQ operators.
This would be the simplest and most robust way of doing queries:
public class IDCollection
{
private IDictionary<string, ID> List = new Dictionary<string, ID>() { { "x", new ID() }, } ;
public IEnumerable<KeyValuePair<string, ID>> AsEnumerable()
{
return List.Select(x => x);
}
}
The queries would have to look like:
var query =
from k in testIDColl.AsEnumerable()
where k.Key == "x"
select k;
The easiest solution is to implement IEnumerable<T>. It's only one method, which you can usually delegate to inner collection's GetEnumerator() or implement easily with yield return.
The name of your type (IDCollection) suggests that it should implement IEnumerable<T>, probably some other collection interface (e.g. ICollection<T>, IReadonlyCollection<T>).
If for some reason you don't want to use IEnumerable<T>, you can still make it work. First you need to understand how the compiler processes query expressions.
A LINQ query expression is first translated by the compiler to a series of method calls. For example the query expression
from KeyValuePair<string, int> item in collection
where item.Key == "abc"
select item.Value;
Is translated to
testIDColl
.Cast<KeyValuePair<string, int>>()
.Where(item => item.Key == "abc")
.Select(item => item.Value);
All you need to do to use a type as a source in a query expression is to make the above code compile. It means you will need Cast, Where, Select (and others too, like GroupBy, OrderBy) methods either as instance methods or extension methods.
For example the following class and extension methods will make the above query expression compile (although the methods don't do anything at all):
class IDCollection
{
}
static class IDCollectionExtensions
{
public static IDCollection Cast<TResult>(this IDCollection source)
{
return source;
}
public static IDCollection Where(this IDCollection source, Func<KeyValuePair<string, int>, bool> selector)
{
return source;
}
public static IDCollection Select<TResult>(this IDCollection source, Func<KeyValuePair<string, int>, TResult> selector)
{
return source;
}
}
Instance methods will work too:
class IDCollection
{
public IDCollection Cast<TResult>()
{
return this;
}
public IDCollection Where(Func<KeyValuePair<string, int>, bool> selector)
{
return this;
}
public IDCollection Select<TResult>(Func<KeyValuePair<string, int>, TResult> selector)
{
return this;
}
}

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.

Generic method for converting string array into list

I would like to create a function that will return list of type that is specified by me at run time.
I tried something along this line:
public static List<T> GetMyList<T>(string[] itemList)
{
List<T> resultList = new List<T>(itemList.Length);
return resultList.AddRange(itemList);
}
But this doesn't work. Obviously I don't fully understand how to pass a type to be converted to.
Any help would be appreciated it.
Edit:
It looks like that it is not possible, but here is more info. String array will contain numbers and I would like to convert those numbers sometimes into int, sometimes into short.
Idea behind is to have a generic function that will attempt to convert items into whatever type list I tell it.
You need to provide a method to convert a string into a T - you can do this using a Func<string, T>:
public static List<T> GetMyList<T>(string[] itemList, Func<string, T> conversionFunc)
{
return itemList.Select(conversionFunc).ToList();
}
e.g.
List<int> ints = GetMyList(new[] { "1", "2", "3" }, s => int.Parse(s));
A slightly more elegant solution would be to add an extension method to string that automatically calls the parser for type T, like so:
public static class GenericParser {
public static T Parse<T>(this string input) {
var converter = TypeDescriptor.GetConverter(typeof(T));
if ( converter != null ) {
return ( T )converter.ConvertFromString(input);
}
return default(T);
}
}
Then, your conversion function would look something like:
public static List<T> GetMyList<T>(string[] itemList) {
List<T> list = new List<T>();
list.AddRange(Array.ConvertAll<string, T>(itemList, delegate(string s) {
return s.Parse<T>();
}));
return list;
}
And the usage would be:
List<int> integers = GetMyList<int>(new []{"1", "2", "3", "4"});
List<double> doubles = GetMyList<double>(new []{"1.0", "2.0", "3.0", "4.0"});
and so on.
My first thought is that this won't work because not every object type can be constructed from a string. Perhaps you want something with a signature more like:
public static List<T> GetMyList<T>(T[] itemList)
{
List resultList = new List(itemList.Length);
foreach (t in itemList)
{
resultList.add(t);
}
return resultList;
}
(forgive my syntax. I don't have a compiler handy right now to check it.)
this doesn't work because system has no idea how to convert string to generic T. Also even if it is known, it will not work, because C# (prior to 4) doesn't have type covariance. So use either foreach to copy and convert elements one by one or use Select from Linq
Similar to Lee's but more generic...
public static class Tools
{
public static List<TResult> ToList<T, TResult>(
this IEnumerable<T> input,
Func<T, TResult> conversion)
{
return input.Select(conversion).ToList();
}
public static List<TResult> ToList<T, TResult>(
this IEnumerable<T> input,
Func<T, int, TResult> conversion)
{
return input.Select(conversion).ToList();
}
}
class Program
{
static void Main(string[] args)
{
var input = new[] { "1", "2", "3" };
var ret = input.ToList(i => int.Parse(i));
// 1,2,3
var ret2 = input.ToList((i,j) => int.Parse(i) + j * 10);
// 1,12,23
}
}

Is there a statement to prepend an element T to a IEnumerable<T>

For example:
string element = 'a';
IEnumerable<string> list = new List<string>{ 'b', 'c', 'd' };
IEnumerable<string> singleList = ???; //singleList yields 'a', 'b', 'c', 'd'
I take it you can't just Insert into the existing list?
Well, you could use new[] {element}.Concat(list).
Otherwise, you could write your own extension method:
public static IEnumerable<T> Prepend<T>(
this IEnumerable<T> values, T value) {
yield return value;
foreach (T item in values) {
yield return item;
}
}
...
var singleList = list.Prepend("a");
Since .NET framework 4.7.1 there is LINQ method for that:
list.Prepend("a");
https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.prepend?view=netframework-4.7.1
public static class IEnumerableExtensions
{
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> ie, T item)
{
return new T[] { item }.Concat(ie);
}
}
You can roll your own:
static IEnumerable<T> Prepend<T>(this IEnumerable<T> seq, T val) {
yield return val;
foreach (T t in seq) {
yield return t;
}
}
And then use it:
IEnumerable<string> singleList = list.Prepend(element);
This would do it...
IEnumerable<string> singleList = new[] {element}.Concat(list);
If you wanted the singleList to be a List then...
IEnumerable<string> singleList = new List<string>() {element}.Concat(list);
... works too.
Also:
IEnumerable<string> items = Enumerable.Repeat(item, 1).Concat(list);
I find it convenient to be able to prepend multiple items in a chainable fashion. This version takes advantage of extension methods and params.
As a note, this version implicitly allows null, but it's just as easy to change it to throw new NullReferenceException() if that's the desired behavior.
public static class IEnumerableExtensions
{
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, params T[] items)
{
return items.Concat(source ?? new T[0]);
}
}
Allows for a very readable syntax for individual items:
GetItems().Prepend(first, second, third);
...and for collections of items:
GetItems().Prepend(GetMoreItems());
Finishing the example in the question results in:
string element = "a";
IEnumerable<string> list = new List<string>{ "b", "c", "d" };
IEnumerable<string> singleList = list.Prepend(element);
No, there's no such built-in statment, statement, but it's trivial to implement such function:
IEnumerable<T> PrependTo<T>(IEnumerable<T> underlyingEnumerable, params T[] values)
{
foreach(T value in values)
yield return value;
foreach(T value in underlyingEnumerable)
yield return value;
}
IEnumerable<string> singleList = PrependTo(list, element);
You can even make it an extension method if C# version allows for.
Just as a reminder - List< T > is not the only type of container. If you find yourself adding elements to the front of the list quite frequently, you can also consider using Stack< T > to implement your container. Once you have a stack
var container = new Stack<string>(new string[] { "b", "c", "d" });
you can always "prepend" an element via
container.Push("a");
and still use the collection as IEnumerable< T > like in
foreach (var s in container)
// do sth with s
besides all the other methods typical for a stack like Pop(), Peek(), ...
Some of the solutions above iterate through the whole IEnumeration< T > just to prepend one element (or more than one in one case). This can be a very expensive operation if your collection contains a large number of elements and the frequency of prepending is relatively high.
Looking at some of the examples, I think I'd prefer to reverse the extension to apply to the object.
public static IEnumerable<T> PrependTo<T>(this T value, IEnumerable<T> values) {
return new[] { value }.Concat(values);
}
Used like
var singleList = element.PrependTo(list);
As pointed out by Niklas & NetMage in the comments.
There is a new built-in Prepend methond in C#.

Categories

Resources