views:

97

answers:

4

From the following simulation

int[] amountWithdrawal = { 10, 20, 30, 140, 50, 70 };

amountWithdrawal.Aggregate(100, (balance, withdrawal) => 
{
  Console.WriteLine("balance :{0},Withdrawal:{1}", balance, withdrawal);
 if (balance >= withdrawal)
 {
   return balance - withdrawal;
 }
 else return balance;
 }
);

I want to terminate the Aggregation when the balance is less than the withdrawal.But my code travels the entire array.How to terminate it?

+1  A: 

You should use Aggregate as normal, then use Where to omit negative balances.

BTW, using functions with side effects (such as Console.WriteLine) inside a LINQ method is bad practice. You're better off doing all of the LINQ aggregation and filtering first, then writing a foreach loop to print to the console.

Tim Robinson
I dont think this is the answer the OP is looking for. He wants to check for a negative balance, not omit it.
leppie
+1  A: 

Replace aggregate with for loop.

Alex Reitbort
+5  A: 

It seems to me that you want an Accumulate method which yields a new sequence of accumulated values, instead of a scalar. Something like this:

public static IEnumerable<TAccumulate> SequenceAggregate<TSource, TAccumulate>(
    this IEnumerable<TSource> source,
    TAccumulate seed,
    Func<TAccumulate, TSource, TAccumulate> func)
{
    TAccumulate current = seed;
    foreach (TSource item in source)
    {
        current = func(current, item);
        yield return current;
    }
}

Then you could apply TakeWhile:

int[] amountWithdrawal = { 10, 20, 30, 140, 50, 70 };

var query = amountWithdrawal.SequenceAggregate(100, (balance, withdrawal) => 
{
  Console.WriteLine("balance :{0},Withdrawal:{1}", balance, withdrawal);
  return balance - withdrawal;
}).TakeWhile (balance => balance >= 0);

I could have sworn there was something like this in normal LINQ to Objects, but I can't find it at the moment...

Jon Skeet
you cant TakeWhile on a scalar value, Jon ;p
leppie
Doh. Got confused with an "aggregate and return new value as series" operator, whose name I currently forget.
Jon Skeet
Fixed using a new operator... I'm still hoping there's an existing operator somewhere...
Jon Skeet
In the F#-library this function is called 'scan' (Microsoft.FSharp.Collections.Seq.scan). I don't believe there's an implementation in the .Net Framework.
Johan Kullbom
A: 

You probably want to use TakeWhile().Aggregate() and check the balance in the take while predicate.

leppie
The balance is only present *after* the aggregation though - which is why I've placed TakeWhile after it.
Jon Skeet
... but as you point out, Aggregate is going to return a scalar anyway. Hmm.
Jon Skeet