【问题标题】:"inflate" either end of array to meet size requirements“膨胀”数组的任一端以满足大小要求
【发布时间】:2018-01-17 19:28:44
【问题描述】:

我有一组复杂的银行交易对象,这些对象被提炼成一组(如果需要,可以为空)小数。在前端,我需要一定数量的“交易总和”才能完全填充数据表。但是,在某些情况下,没有足够的事务来填充数组大小,这会破坏 UI。

这是构造数组的 C# ViewModel 代码的一部分:

var minDate = this.Periods[0].FirstDayOfMonth(); // 11/1/2016
var maxDate = this.Periods[this.NumberOfPeriods - 1].LastDayOfMonth(); // 11/20/2017

this.NetCashReceipts = this.NetCashReceiptsCredits
                .Where(bt => bt.Date.Between(minDate, maxDate, true))
                .GroupBy(bt => bt.Date.FirstDayOfMonth())
                .ToDictionary(group => group.Key, group => group.Sum(bt => bt.Amount))
                .OrderBy(kvp => kvp.Key)
                .Select(kvp => kvp.Value)
                .ToArray();

Select 语句之前,有序字典数据如下所示:

{System.Collections.Generic.KeyValuePair<System.DateTime, decimal>[11]}
    [0]: {[1/1/2017 12:00:00 AM, 27172.13]}
    [1]: {[2/1/2017 12:00:00 AM, 5080.18]}
    [2]: {[3/1/2017 12:00:00 AM, 63934.53]}
    [3]: {[4/1/2017 12:00:00 AM, 30006.93]}
    [4]: {[5/1/2017 12:00:00 AM, 64821.43]}
    [5]: {[6/1/2017 12:00:00 AM, 19161.06]}
    [6]: {[7/1/2017 12:00:00 AM, 130019.11]}
    [7]: {[8/1/2017 12:00:00 AM, 132176.08]}
    [8]: {[9/1/2017 12:00:00 AM, 72991.46]}
    [9]: {[10/1/2017 12:00:00 AM, 14440.88]}
    [10]: {[11/1/2017 12:00:00 AM, 18057.63]}

请注意,最早的交易是 2017 年 1 月 1 日,即 2016 年 11 月 1 日之后的两个月。未来所有涉及此数据的代码都将因倾斜我的表格而失败,更不用说IndexOutOfRangeExceptions

我想在while 循环中检查字典的第一个日期和最后一个日期,并将项目添加到数组的开头或结尾(如果需要,可以添加一个新数组),直到我的数组正确尺寸。 这是唯一的方法吗?还是有一些LINQ 魔法可以帮助解决这个问题?或者更高效的方法?

工作代码的预期结果将在没有事务的地方包含null,如下所示:

{System.Collections.Generic.KeyValuePair<System.DateTime, decimal>[11]}
    [0]: {[11/1/2016 12:00:00 AM, null]}
    [1]: {[12/1/2016 12:00:00 AM, null]}
    [2]: {[1/1/2017 12:00:00 AM, 27172.13]}
    [3]: {[2/1/2017 12:00:00 AM, 5080.18]}
    [4]: {[3/1/2017 12:00:00 AM, 63934.53]}
    [5]: {[4/1/2017 12:00:00 AM, 30006.93]}
    [6]: {[5/1/2017 12:00:00 AM, 64821.43]}
    [7]: {[6/1/2017 12:00:00 AM, 19161.06]}
    [8]: {[7/1/2017 12:00:00 AM, 130019.11]}
    [9]: {[8/1/2017 12:00:00 AM, 132176.08]}
    [10]: {[9/1/2017 12:00:00 AM, 72991.46]}
    [11]: {[10/1/2017 12:00:00 AM, 14440.88]}
    [12]: {[11/1/2017 12:00:00 AM, 18057.63]}

*null 值将允许我使用N/a 而不是0 填充我的前端数据表。

【问题讨论】:

  • 你为什么使用数组而不是 List&lt;T&gt; 或其他通用集合?
  • 因为this.NetCashReceiptsdecimal?[],而这个设计决策早于我。我愿意根据需要进行选角、更改等。
  • 您可以将属性更改为List&lt;decimal?&gt;,然后您无需担心调整大小。或者更可能只是一个 List&lt;decimal&gt; 并且不要向其添加空值。

标签: c# arrays linq


【解决方案1】:

使用 Linq 没有直接的方法可以做到这一点,但 Linq 并不神奇,有人编写了所有这些扩展方法。如果您找不到适合您需求的产品,那么只需实施一个适合您的产品!

在这种情况下,您需要一个自定义 Take 来填充输出。填充末端总是更容易,因此您可以执行以下操作:

public static IEnumerable<TSource> TakeAndPadEnd<TSource>(
    this IEnumerable<TSource>source, 
    int count,
    Func<TSource, TSource> paddedValueSelector)
{
    var yielded = 0;
    var previous = default(TSource);

    using (var e = source.GetEnumerator())
    {
        while (e.MoveNext())
        {
            yield return e.Current;
            previous = e.Current;
            yielded += 1;

            if (yielded == count)
                yield break;
        }
    }

    while (yielded < count)
    {
        var newValue = paddedValueSelector(previous);
        yield return newValue;
        previous = newValue;
        yielded += 1;
    }
}

你会使用它:

this.NetCashReceipts = TakeAndPadd(
    12,
    this.NetCashReceiptsCredits
        .Where(bt => bt.Date.Between(minDate, maxDate, true))
        .GroupBy(bt => bt.Date.FirstDayOfMonth())
        .ToDictionary(
            group => group.Key, 
            group => group.Sum(bt => bt.Amount))
        .OrderBy(kvp => kvp.Key)
        .Select(kvp => kvp.Value),
    v => default(decimal?)).ToArray();

更新:删除了元组解决方案,因为它是多余的,上面显示的解决方案就足够了; TSource 可以是任何东西。

【讨论】:

    【解决方案2】:

    你应该这样做:

    List<decimal?> LNetCashReceipts = NetCashReceipts.ToList<decimal?>();
    

    然后继续努力。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-03
      • 1970-01-01
      • 2011-08-25
      • 1970-01-01
      • 2015-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多