I have never been really good at C# and I am trying to better myself by learing new things. I am now trying lambda's.
this is my code so far:
public static Func<float[], bool[]> CategoricalMap(Func<float, bool> mapper)
{
Func<float[], bool[]> fun = x => new bool[] { true };
return fun;
}
public static void Main()
{
Func<float, bool> success = x => x == 5.5f;
var result = CategoricalMap(success)(new float[] { 4f, 5.5f, 3.5f, -5.5f, 10.2f });
Console.ReadKey();
}
What I am trying to do is, to check what number is equal to 5.5f, but I don't know how to get the floats to show up in the CategoricalMap function. I know a bit of the puzzle, I have to do this:
mapper(float);
but I don't know how to get the floats from result to the function.
Please help.
Edit 1
I think I should make things more clear, A few weeks ago asked a someone to give me lambda challenges, sadly I have no way of contacting him. (kinda stupid of me)
this is what he gave me:
Create the lambda success which returns true if the given value is above or equal to 5.5f
Create the following function:
CategoricalMap
Creates a mapper function
Input: mapper a function of type Func<float, bool>
Output: a function of type Func<float[], bool[]> that takes in an array of booleans and applies the function mapper to each of the elements and stores the results in an integer array
Func<float[], bool[]> fun = x => new bool[] { true };
There x is your argument and it has type float[]. So in fact it is an array which you can iterate:
Func<float[], bool[]> fun = x => {
var result = new bool[x.Length];
for(int i = 0; i < x.Length; ++i) {
result[i] = mapper(x[i]);
}
return result;
};
Now you can use it as
public static Func<float[], bool[]> CategoricalMap(Func<float, bool> mapper)
{
Func<float[], bool[]> fun = x => {
var result = new bool[x.Length];
for(int i = 0; i < x.Length; ++i) {
result[i] = mapper(x[i]);
}
return result;
};
return fun;
}
public static void Main()
{
Func<float, bool> success = x => x == 5.5f;
var result = CategoricalMap(success)(new float[] { 4f, 5.5f, 3.5f, -5.5f, 10.2f });
Console.ReadKey();
}
But don't do that. This approach is terrible.
Related
This method should return a function which can evaluate the scalar product of two vectors of the same size:
public static Func<T[], T[], T> GetVectorMultiplyFunction<T>() where T : struct
{
var x = Expression.Parameter(typeof(T[]), "x");
var y = Expression.Parameter(typeof(T[]), "y");
var body = Enumerable
.Range(0, 3 /*Expression.ArrayLength(x)*/)
.Select(i => Expression.Multiply(
Expression.ArrayIndex(x, Expression.Constant(i)),
Expression.ArrayIndex(y, Expression.Constant(i))
))
.Aggregate(Expression.Add);
var lambda = Expression.Lambda<Func<T[], T[], T>>(body, x, y);
return lambda.Compile();
}
But in order to do that, I need to know the length of an array. There's a method Expression.ArrayLength() which returns UnaryExpression instead of the int and the expression cannot be cast explicitly to int. Is there a way of evaluating the array length as int beforehand?
UPD
Here's a unit test showing how this method should work:
[Test]
public void GetVectorMultiplyFunctionReturnsFunctionForInt()
{
var first = new int[] { 1, 2, 3 };
var second = new int[] { 2, 2, 2 };
var expected = 1 * 2 + 2 * 2 + 3 * 2;
var func = GetVectorMultiplyFunction<int>();
var actual = func(first, second);
Assert.AreEqual(expected, actual);
}
The length of an array is not part of the type definition, it's a value you can only obtain at runtime.
With the recent introduction of Generic Math, you can multiply and add values using generics without needing to build an expression tree;
public static T Calc<T>(T[] x, T[] y)
where T : struct, IMultiplyOperators<T,T,T>, IAdditionOperators<T,T,T>
{
T result = default(T);
for(var i = 0; i < x.Length && i < y.Length; i++)
result += x[i] * y[i];
return result;
}
But I assume that for your assignment you are expected to build an expression tree equivalent to the above method, then compile it.
This may not be what you want but seems to solve your problem if all you need to retain is the signature:
public static Func<T[], T[], T> GetVectorMultiplyFunction<T>() where T : struct
{
return (T[] x, T[] y) => {
T result = default(T);
for(var i = 0; i < x.Length; i++)
{
var xd = (dynamic)x[i];
var yd = (dynamic)y[i];
result += (xd * yd);
}
return result;
};
The only parts of your code that require expression trees (assuming you can't use generic math or dynamics as per the other two solutions) are the operators (add and multiply).
If you compile the operator expressions separately, you can then use LINQ very easily, as per your original approach - something like this:
public static Func<T[], T[], T> GetVectorMultiplyFunction<T>() where T : struct
{
static Func<T,T,T> GetOperatorFunction(Func<Expression, Expression, BinaryExpression> operatorExpression)
{
var x = Expression.Parameter(typeof(T));
var y = Expression.Parameter(typeof(T));
var body = operatorExpression(x, y);
return Expression
.Lambda<Func<T, T, T>>(body, x, y)
.Compile();
}
var add = GetOperatorFunction(Expression.Add);
var multiply = GetOperatorFunction(Expression.Multiply);
return (xVector, yVector) =>
xVector
.Zip(yVector, multiply)
.Aggregate(add);
}
I have a rule to select an option at random:
.RuleFor(c=>field, x=>x.PickRandom("Option1", "Option2", "Option3", "Option4"))
With a default value, I can alter the probability of one of the items. I would like to set the probabilities of all four items. Option1 would be picked 50% of the time, Option2 would be picked 30%, then 15% for Option3, and 5% for Option4.
I would like to use a WeightedRandom:
.RuleFor(c=>field, x=>PickWeightedRandom(valueArray, weightArray)
There is no such method as PickWeightedRandom, but WeightedRandom is a method in the Randomizer class. How do I get the WeightedRandom to work?
EDIT: Maybe an extension method?
The following seems to work:
void Main()
{
var items = new []{"kiwi", "orange", "cherry", "apple"};
var weights = new[]{0.1f, 0.1f, 0.2f, 0.6f};
var faveFaker = new Faker<Favorite>()
.RuleFor(x => x.Fruit, f => f.Random.WeightedRandom(items, weights));
faveFaker.Generate(10).Dump();
}
public class Favorite
{
public string Fruit {get;set;}
}
Of course, using C# extension methods are always an excellent way to extend Bogus to best suit your API needs:
void Main()
{
var faveFaker = new Faker<Favorite>()
.RuleFor(x => x.Fruit, f => f.WeightedRandom( ("kiwi", 0.1f), ("orange", 0.1f),
("cherry", 0.2f), ("apple", 0.6f)) );
faveFaker.Generate(10).Dump();
}
public class Favorite
{
public string Fruit {get;set;}
}
public static class MyExtensionsForBogus
{
public static T WeightedRandom<T>(this Faker f, params (T item, float weight)[] items)
{
var weights = items.Select(i => i.weight).ToArray();
var choices = items.Select(i => i.item).ToArray();
return f.Random.WeightedRandom(choices, weights);
}
}
One answer is to pick the random string somewhere else, then use the => operator to point to the result.
public static string PickAString(string[] items, float[] weights)
{
// hopefully all the weights will add up to 1. If not, this method may throw for array out of bounds.
// Also, it would be best if the number of items in each array is the same, to prevent out of bounds exception.
// generate a number from 0 to less than 1
double randomValue = random.NextDouble();
double weightSum = 0;
for (int i = 0; i < items.Length; i++)
{
weightSum += weights[i];
if (randomValue < weightSum)
return items[i];
}
return null; // if the weights don't add up.
}
.RuleFor(c => c.field, _ =>
{
return PickAString(values, weights);
})
This works, but it would be more elegant to add this to the library.
I want to create list of method. and run this list of method in order.
The input of next method is output of current method.
So, this is my code for these, and i need to get input, output type.
static void Main( string [ ] args )
{
List<dynamic> temp = new List<dynamic>();
Func<int,int> fn1 = new Func<int,int>( x => 3);
Func<int,int> fn2 = new Func<int,int>(x => x + 3);
Func<int,int> fn3 = new Func<int,int>(x => x + 30);
Func<int,double> fn4 = new Func<int,double>(x => x*0.2);
temp.Add( fn1 );
temp.Add( fn2 );
temp.Add( fn3 );
temp.Add( fn4 );
int input = 6;
// use for or foreach or something
// output ?
}
Yes, you can use foreach, and call Invoke dynamically - you'll need the input to be dynamic as well though:
using System;
using System.Collections.Generic;
class Test
{
static void Main()
{
Func<int,int> fn1 = new Func<int,int>(x => 3);
Func<int,int> fn2 = new Func<int,int>(x => x + 3);
Func<int,int> fn3 = new Func<int,int>(x => x + 30);
Func<int,double> fn4 = new Func<int,double>(x => x * 0.2);
List<dynamic> pipeline = new List<dynamic> { fn1, fn2, fn3, fn4 };
dynamic current = 6;
foreach (dynamic stage in pipeline)
{
// current = stage(current) would work too, but I think it's less clear
current = stage.Invoke(current);
}
Console.WriteLine($"Result: {current}");
}
}
(It's odd that your first function ignores the input, by the way.)
Note that there's no compile-time type safety here - if one of your functions actually required a string, you'd only find out at execution time. Without knowing how you're creating the delegates in your real code, it's hard to know exactly the best way to fix this, but here's one option:
class Pipeline<TInput, TOutput>
{
private readonly Func<TInput, TOutput> function;
public Pipeline(Func<TInput, TOutput> function)
{
this.function = function;
}
public Pipeline<TInput, TNext> Then<TNext>(Func<TOutput, TNext> nextFunction) =>
new Pipeline<TInput, TNext>(input => nextFunction(function(input)));
public TOutput Process(TInput input) => function(input);
}
class Test
{
static void Main()
{
Pipeline<int, double> pipeline = new Pipeline<int, int>(x => 3)
.Then(x => x + 3)
.Then(x => x + 30)
.Then(x => x * 0.2);
var result = pipeline.Process(6);
Console.WriteLine($"Result: {result}");
}
}
I need something similar to an AggregateWhile method. The standard System.Linq.Enumerable class doesn't provide it. Until now I've always been able to leverage the standard LINQ methods to solve every problem I've encountered. So I'd like to know if that's still possible in this case, or if I really do need to extend LINQ with a non-standard method.
The hypothetical AggregateWhile method would iterate over a sequence and apply the accumulator. The aggregation would be complete once a predicate returns false. The result is the aggregration of elements up to but not including the element for which the predicate failed.
Here's an example. We have a List { 1, 2, 3, 4, 5 } with an accumulator that adds the two input numbers together, and a predicate that states the accumulation must be less than 12. AggregateWhile would return 10 since that's the result of 1 + 2 + 3 + 4 and adding the final 5 would push the total over the limit. In code:
var list = new List<int> { 1, 2, 3, 4, 5 };
int total = list.AggregateWhile( (x, y) => x + y, a => a < 12 ); // returns 10
I need a purely functional solution, so closing over a temporary variable is not an option.
You could either write the function yourself, or carry a flag with your accumulator:
int total = list.Aggregate(new { value = 0, valid = true },
(acc, v) => acc.value + v < 12 && acc.valid ?
new { value = acc.value + v, valid = true } :
new { value = acc.value, valid = false },
acc => acc.value);
It's quite ugly, so writting a new AggregateWhile would be nicer:
public static TSource AggregateWhile<TSource>(this IEnumerable<TSource> source,
Func<TSource, TSource, TSource> func,
Func<TSource, bool> predicate)
{
using (IEnumerator<TSource> e = source.GetEnumerator()) {
TSource result = e.Current;
TSource tmp = default(TSource);
while (e.MoveNext() && predicate(tmp = func(result, e.Current)))
result = tmp;
return result;
}
}
(no error checking for brevity)
You can write your own extension method. This is not as perfect as the normal Linq methods, I cheated because I already know your requirements to make it simpler. In reality you may want an optional starting value for a and maybe different In and output types for T or other stuff:
public static class Linq
{
public static T AggregateWhile<T>(this IEnumerable<T> sequence, Func<T, T, T> aggregate, Func<T, bool> predicate)
{
T a;
foreach(var value in sequence)
{
T temp = aggregate(a, value);
if(!predicate(temp)) break;
a = temp;
}
return a;
}
}
Won't this work?
int total = list.Aggregate(0, (a, x) => (a + x) > 12 ? a : a + x);
Using Tuple<bool, int> as accumulator type, to break on first overflow:
int total = list.Aggregate(new Tuple<bool, int>(false, 0),
(a, x) => a.Item1 || (a.Item2 + x) > 12
? new Tuple<bool, int>(true, a.Item2)
: new Tuple<bool, int>(false, a.Item2 + x)
).Item2;
But it isn't so nice unfortunately.
Start using F#. ;)
let list = [ 1; 2; 3; 4; 5; 1 ]
let predicate = fun a -> a > 12
let total = list |> List.fold (fun (aval, astate) x ->
if astate || predicate (aval + x)
then (aval, true)
else (aval + x, false)) (0, false)
Tuple unpacking, no new bloat. And when you code it type inference makes it a breeze.
I asked this question a while back while encountering a problem that I later reframed into not needing AggregateWhile. But now I've encountered a slightly different problem which undoubtedly requires AggregateWhile or some direct substitute for it.
The solutions proposed by #sloth and #rkrahl are helpful. But they fall short in that the aggregation logic (addition in this case) is repeated twice. This doesn't seem like a big deal for the question's trivial example. But for my real problem, the calculation is complex so writing it twice is unacceptable.
Here's the solution I prefer (short of actual AggregateWhile methods):
class Program
{
static void Main( string[] args ) { new Program(); }
public Program()
{
var list = new int[] { 1, 2, 3, 4, 5 };
int total = list
.Aggregate( new Accumulator( 0 ), ( a, i ) => a.Next( i ), a => a.Total );
}
}
class Accumulator
{
public Accumulator( int total )
{
this.total = total;
}
public Accumulator Next( int i )
{
if ( isDone )
return this;
else {
int total = this.total + i;
if ( total < 12 )
return new Accumulator( total );
else {
isDone = true;
return this;
}
}
}
bool isDone;
public int Total
{
get { return total; }
}
readonly int total;
}
The ideal solution are fully implemented and tested AggregateWhile methods which correspond to the three Aggregate overloads. Short of that, the above pattern has the advantage that it can leverage the (somewhat lacking) functionality that's already present in the .NET framework.
Here is an AggregateWhile with a seed:
public static TAccumulate AggregateWhile<TSource, TAccumulate>(
this IEnumerable<TSource> source,
TAccumulate seed,
Func<TAccumulate, TSource, TAccumulate> func,
Func<TAccumulate, bool> predicate)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (func == null)
throw new ArgumentNullException(nameof(func));
if (predicate == null)
throw new ArgumentNullException(nameof(predicate));
var accumulate = seed;
foreach (var item in source)
{
var tmp = func(accumulate, item);
if (!predicate(tmp)) break;
accumulate = tmp;
}
return accumulate;
}
I have a csv string containing doubles (e.g "0.3,0.4,0.3"), and I want to be able to output a double array containing the cumulative sum of these numbers (e.g [0.3,0.7,1.0]).
So far, I have
double[] probabilities = textBox_f.Text.Split(new char[]{','}).Select(s => double.Parse(s)).ToArray();
which gives the numbers as an array, but not the cumulative sum of the numbers.
Is there any way to continue this expression to get what I want, or do I need to use iteration to create a new array from the array I already have?
There's a time for generality, and there's a time for solving the problem actually posed. This is one of the latter times. If you want to make a method that turns a sequence of doubles into a sequence of partial sums, then just do that:
public static IEnumerable<double> CumulativeSum(this IEnumerable<double> sequence)
{
double sum = 0;
foreach(var item in sequence)
{
sum += item;
yield return sum;
}
}
Easy. No messing around with aggregates and complicated queries and whatnot. Easy to understand, easy to debug, easy to use:
textBox_f.Text
.Split(new char[]{','})
.Select(s => double.Parse(s))
.CumulativeSum()
.ToArray();
Now, I note that if that is user input then double.Parse can throw an exception; it might be a better idea to do something like:
public static double? MyParseDouble(this string s)
{
double d;
if (double.TryParse(s, out d))
return d;
return null;
}
public static IEnumerable<double?> CumulativeSum(this IEnumerable<double?> sequence)
{
double? sum = 0;
foreach(var item in sequence)
{
sum += item;
yield return sum;
}
}
...
textBox_f.Text
.Split(new char[]{','})
.Select(s => s.MyParseDouble())
.CumulativeSum()
.ToArray();
and now you don't get an exception if the user makes a typing mistake; you get nulls.
I had a similar requirement some time ago. Basically, I needed to do an aggregation, but I also needed to select each intermediate value. So I wrote an extension method named SelectAggregate (probably not the most appropriate name, but I couldn't find anything better then) that can be used like that:
double[] numbers = new [] { 0.3, 0.4, 0.3 };
double[] cumulativeSums = numbers.SelectAggregate(0.0, (acc, x) => acc + x).ToArray();
Here's the code :
public static IEnumerable<TAccumulate> SelectAggregate<TSource, TAccumulate>(
this IEnumerable<TSource> source,
TAccumulate seed,
Func<TAccumulate, TSource, TAccumulate> func)
{
source.CheckArgumentNull("source");
func.CheckArgumentNull("func");
return source.SelectAggregateIterator(seed, func);
}
private static IEnumerable<TAccumulate> SelectAggregateIterator<TSource, TAccumulate>(
this IEnumerable<TSource> source,
TAccumulate seed,
Func<TAccumulate, TSource, TAccumulate> func)
{
TAccumulate previous = seed;
foreach (var item in source)
{
TAccumulate result = func(previous, item);
previous = result;
yield return result;
}
}
You want to use the Aggregate operator, with a List<double> as the aggregation accumulator. That way you can produce a projection which is itself a sequence of sums.
Here's an example to get you started:
double[] runningTotal = textBox_f.Text
.Split(new char[]{','})
.Select(s => double.Parse(s))
.Aggregate((IEnumerable<double>)new List<double>(),
(a,i) => a.Concat(new[]{a.LastOrDefault() + i}))
.ToArray();
var input=new double[]{ ... }
double sum=0;
var output=input
.Select(w=>sum+=w);
Why does it need to be LINQ?
var cumulative = new double[probabilities.Length];
for (int i = 0; i < probabilities.Length; i++)
cumulative[i] = probabilities[i] + (i == 0 ? 0 : cumulative[i-1]);
First of all i don't think that it is good task for Linq. Plain old foreach will do it better. But as a puzzle it is fine.
First idea was to use subqueries, but i don't like it, because it is O(n^2). Here is my linear solution:
double[] probabilities = new double[] { 0.3, 0.4, 0.3};
probabilities
.Aggregate(
new {sum=Enumerable.Empty<double>(), last = 0.0d},
(a, c) => new {
sum = a.sum.Concat(Enumerable.Repeat(a.last+c,1)),
last = a.last + c
},
a => a.sum
);
use RX :
var input=new double[]{ ... }
var output = new List<double>();
input.ToObservable().Scan((e, f) => f + e).Subscribe(output.Add);
This is actually pretty straightforward to generalize using generator. Here is a new extension method called Accumulate that works like a combination of Select and Aggregate. It returns a new sequence by applying a binary function to each element in the sequence and accumulated value so far.
public static class EnumerableHelpers
{
public static IEnumerable<U> Accumulate<T, U>(this IEnumerable<T> self, U init, Func<U, T, U> f)
{
foreach (var x in self)
yield return init = f(init, x);
}
public static IEnumerable<T> Accumulate<T>(this IEnumerable<T> self, Func<T, T, T> f)
{
return self.Accumulate(default(T), f);
}
public static IEnumerable<double> PartialSums(this IEnumerable<double> self)
{
return self.Accumulate((x, y) => x + y);
}
public static IEnumerable<int> PartialSums(this IEnumerable<int> self)
{
return self.Accumulate((x, y) => x + y);
}
}
Here's my solution:
Linq
linear time
linear memory
no side effects
Only caveat is that it doesn't work for empty lists (trivial to handle).
var doublesSummed = doubles.Skip(1).Aggregate(
new {
sum = doubles.First(),
doubles = new [] {doubles.First()}.AsEnumerable()
},
(acc, nextDouble) => new {
sum = acc.sum + nextDouble,
doubles = acc.doubles.Append(acc.sum + nextDouble)
}
);
Demo
Here's a way of doing it using LINQ:
double[] doubles = { 1.7, 2.3, 1.9, 4.1, 2.9 };
var doublesSummed = new List<double>();
Enumerable.Aggregate(doubles, (runningSum, nextFactor) => {
double currentSum = runningSum + nextFactor;
doublesSummed.Add(currentSum);
return currentSum;
});
doublesSummed.Dump();
In LINQPad:
4
5.9
10
12.9
Cumulative sum for List<double>:
var nums = new List<double>() { 0.3, 0.0, 0.4, 1.1 };
var cumsum = nums.Aggregate(new List<double> (),
(list, next) => { list.Add(list.LastOrDefault() + next); return list; });