c# linq语句计算12个月的余额



我在试着画一个流线图。我希望x轴是一月到十二月的月份y轴是账户余额。我有这个账户在12个月内的收入和支出,但减去它们只会得到当月的差额,而不会加上上个月的余额。

这是我如何得到的收入和支出范围:

var monthsToDate = Enumerable.Range(1, 12)
                                .Select(m => new DateTime(DateTime.Today.Year, m, 1))
                                .ToList();
            var sums = from month in monthsToDate
                       select new
                       {
                           month = month,
                           income = (from account in household.Accounts
                                     from transaction in account.Transactions
                                     where transaction.IsIncome && transaction.Created.Month == month.Month
                                     select transaction.Amount).DefaultIfEmpty().Sum(),
                           expense = (from account in household.Accounts
                                      from transaction in account.Transactions
                                      where !transaction.IsIncome && transaction.Created.Month == month.Month
                                      select transaction.Amount).DefaultIfEmpty().Sum(),                                                              
                       };

我得到的是这个

.
.
.
[4] = { month = {5/1/2015 12:00:00 AM}, income = 3000, expense = 1804.75 }
[5] = { month = {6/1/2015 12:00:00 AM}, income = 2500, expense = 1560 }
[6] = { month = {7/1/2015 12:00:00 AM}, income = 0, expense = 550 }
.
.
.

您可以将这个可重用的扩展方法添加到您的代码中:

internal static class CollectionExtensions
{
    /// <summary>
    /// Returns a sequence whose first element is the first element of the source sequence (if any),
    /// and every subsequent element is the result of applying a specified accumulator function to the
    /// previous element of the resulting sequence and the next member of the source sequence.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="source"></param>
    /// <param name="accumulator"></param>
    /// <returns></returns>
    public static IEnumerable<T> Accumulate<T>(this IEnumerable<T> source, Func<T, T, T> accumulator)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (accumulator == null) throw new ArgumentNullException("accumulator");
        return source.AccumulateImpl(accumulator);
    }
    private static IEnumerable<T> AccumulateImpl<T>(this IEnumerable<T> source, Func<T, T, T> accumulator)
    {
        using (var enumerator = source.GetEnumerator())
        {
            T accumulation;
            T next;
            if (enumerator.MoveNext())
                accumulation = enumerator.Current;
            else yield break;
            yield return accumulation;
            if (enumerator.MoveNext())
                next = enumerator.Current;
            else yield break;
            while (true)
            {
                accumulation = accumulator(accumulation, next);
                yield return accumulation;
                if (enumerator.MoveNext())
                    next = enumerator.Current;
                else yield break;
            }
        }
    }
}

使用例子:

var range = Enumerable.Range(0, 5);                     // 0, 1, 2, 3, 4
var accumulated = range.Accumulate((x, y) => x + y);    // 0, 1, 3, 6, 10

现在,如果您将select更改为返回命名类型,而不是匿名类型(我假设您正在使用decimal赚钱-如果不是,您可以调整此代码):

internal class MonthlyIncomeAndExpenses
{
    public DateTime Month { get; set; }
    public decimal Income { get; set; }
    public decimal Expenses { get; set; }
}
var sums = from month in monthsToDate
           select new MonthlyIncomeAndExpenses
           {
               Month = month,
               Income = ...,   // what you already have
               Expense = ...,  // what you already have                                                            
           };

那么你只需要添加一行:

var accumulated = sums.Accumulate((previous, next) => new MonthlyIncomeAndExpenses
{
    Month = next.Month,
    Income = previous.Income + next.Income,
    Expense = previous.Expense + next.Expense,
});

由于您需要一个数组的数组,因此您可以在数组上运行一个循环,并总结前一个月的收入和支出。类似这样的内容(在现有代码之后):

var flotDataAsList = new List<double[]>();
double balance = 0.0;
for (int i = 0; i <= 12; i++)
{
    DateTime thisMonth = new DateTime(year, i, 1);
    balance += sums.Where(m => m.month == thisMonth).Sum(m => m.income - m.expense);
    flotDataAsList .Add(new double[] { GetJavascriptTimestamp(thisMonth), balance });
}
var flotDataAsArray = flotDataAsList.ToArray();

GetJavascriptTimestamp()方法可参考flot文档:

public static int GetJavascriptTimestamp(System.DateTime input)
{
    System.TimeSpan span = new System.TimeSpan(System.DateTime.Parse("1/1/1970").Ticks);
    System.DateTime time = input.Subtract(span);
    return (long)(time.Ticks / 10000);
}

相关内容

  • 没有找到相关文章

最新更新