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 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 two methods where the only difference is one lambda predicate:
public static double LowerQuartile(this IOrderedEnumerable<double> list)
{
var median = list.Median();
var elements = list.Where(x => x < median).ToList();
if (!list.Contains(median))
elements.Add(median);
return elements.OrderBy(x => x).Median();
}
public static double UpperQuartile(this IOrderedEnumerable<double> list)
{
var median = list.Median();
var elements = list.Where(x => x > median).ToList();
if (!list.Contains(median))
elements.Add(median);
return elements.OrderBy(x => x).Median();
}
So I want to join them and pass a lambda as parameter. I tried with something like this:
public static double CalculateQuartile(IOrderedEnumerable<double> list, Expression<Func<IOrderedEnumerable<double>,bool>> predicate)
{
var median = list.Median();
var elements = list.Where(predicate).ToList();
if (!list.Contains(median))
elements.Add(median);
return elements.OrderBy(x => x).Median();
}
But it doesn't work. How could I do it?
It can be something like this
public static double Quartile(this IOrderedEnumerable<double> list,
Func<double,double,bool> predicate)
{
var median = list.Median();
var elements = list.Where(x=>predicate(x,median)).ToList();
if (!list.Contains(median))
elements.Add(median);
return elements.OrderBy(x => x).Median();
}
and you can use as
var val = list.Quartile((x, y) => x > y);
The lambdas x => x < median and x => x > median are both of the type Func<double, bool>. As you do have the median as another variable inside, you will have to accept that as a parameter too, so you would end up with Func<double, double, bool>:
public static double CalculateQuartile(this IOrderedEnumerable<double> list,
Func<double, double, bool> predicate)
{ … }
You could do it as an expression and paste in the reference to median at run-time, but I would suggest against it.
Instead, I would recommend you to solve this in a way, where the user of your function does not need to specify the correct lambda for it to work. After all, you just have two cases: upper quartile and lower quartile. So you might simply want to have a boolean flag as a parameter instead which allows you to choose between lower an upper quartile:
public static double CalculateQuartile(this IOrderedEnumerable<double> list,
bool calculateUpperQuartile = false)
{
var median = list.Median();
var predicate = calculateUpperQuartile ? (x => x > median) : (x => x < median);
var elements = list.Where(predicate).ToList();
if (!list.Contains(median))
elements.Add(median);
return elements.OrderBy(x => x).Median();
}
To make it more usable by the user, I would still offer both a CalculateUpperQuartile and CalculateLowerQuartile function though—but of course, you can internally use a single implementation to handle both.
Can I read two linked-lists in one foreach?
How can I do it?
This is my code:
LinkedList<Double> estimatedProxiSize = new LinkedList<Double>();
LinkedList<Double> planAddedAndModifiedSize = new LinkedList<Double>();
estimatedProxiSize.AddLast(Convert.ToDouble(130));
estimatedProxiSize.AddLast(Convert.ToDouble(650));
estimatedProxiSize.AddLast(Convert.ToDouble(99));
estimatedProxiSize.AddLast(Convert.ToDouble(150));
estimatedProxiSize.AddLast(Convert.ToDouble(128));
planAddedAndModifiedSize.AddLast(Convert.ToDouble(163));
planAddedAndModifiedSize.AddLast(Convert.ToDouble(765));
planAddedAndModifiedSize.AddLast(Convert.ToDouble(141));
planAddedAndModifiedSize.AddLast(Convert.ToDouble(166));
planAddedAndModifiedSize.AddLast(Convert.ToDouble(137));
calc(listaX,listaY);
public void calc(LinkedList<Double> listaX, LinkedList<Double> listaY)
{
//Here, I need something like:
foreach (var itemx in listaX and var itemy)
{
Double xy = itemx*itemxy;
}
}
Is it possible?
Or is there a better way to do it?
If both LinkedList(T) are the same size then Enumerable.Zip will work.
Otherwise you can roll your own:
public static class EnumerableExtensions
{
public static IEnumerable<TResult> Zip<T, TResult>(
this IEnumerable<T> first,
IEnumerable<T> second,
Func<T, T, TResult> resultSelector
)
{
using(var firstEnumerator = first.GetEnumerator())
using(var secondEnumerator = second.GetEnumerator())
{
while(firstEnumerator.MoveNext() && secondEnumerator.MoveNext())
{
yield return resultSelector(firstEnumerator.Current,
secondEnumerator.Current);
}
}
}
}
Usage:
foreach(var item in listaX.Zip(listaY, (x, y) => x * y)
{
}
You can use Zip to combine the items from each list that are in the same position into a single object, and then iterate that resulting sequence:
var zipped = listaX.Zip(listaY, (x, y)=>new{x,y});
foreach(var pair in zipped)
{
double product = pair.x * pair.y;
}
Or, to simplify a bit to this specific case:
var products = listaX.Zip(listaY, (x, y) => x * y);
foreach(double product in products)
{
//do stuff with product
}
If estimatedProxiSize and planAddedAndModifiedSize have the same number of elements you can use IEnumrable<T>.Zip:
estimatedProxiSize.Zip(planAddedAndModifiedSize,(estim,plan)=> estim * plan));
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; });