C # -Терминация в совокупности () - PullRequest
2 голосов
/ 03 декабря 2009

из следующего моделирования

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;
 }
);

Я хочу прекратить агрегирование when the balance is less than the withdrawal. Но мой код перемещается по всему массиву. Как его прекратить?

Ответы [ 4 ]

5 голосов
/ 03 декабря 2009

Мне кажется, что вам нужен метод Accumulate, который выдает новую последовательность накопленных значений вместо скаляра. Как то так:

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;
    }
}

Тогда вы можете подать заявку 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);

Я мог бы поклясться, что что-то подобное было в обычном LINQ to Objects, но я не могу найти это в данный момент ...

1 голос
/ 03 декабря 2009

Замените агрегат на цикл.

1 голос
/ 03 декабря 2009

Вы должны использовать Aggregate как обычно, а затем Where, чтобы исключить отрицательные сальдо.

Кстати, использование функций с побочными эффектами (например, Console.WriteLine) внутри метода LINQ - плохая практика. Вам лучше сначала выполнить все агрегацию и фильтрацию LINQ, а затем написать цикл foreach для печати на консоль.

0 голосов
/ 03 декабря 2009

Возможно, вы захотите использовать TakeWhile().Aggregate() и проверить баланс в предикате дубля во время.

...