C# 创建一个;“随着时间的推移”;算法

C# 创建一个;“随着时间的推移”;算法,c#,.net,algorithm,design-patterns,C#,.net,Algorithm,Design Patterns,我拥有的是一个LineItem对象和一个名为LineItems的集合,其中包含LineItem对象。我的LineItem对象有一个名为ItemDate(日期时间数据类型)的属性,另一个名为ItemAmount(十进制数据类型)的属性和另一个名为ItemCategory(整数数据类型)的属性 我要做的是在我的集合对象中编写一个函数,该函数将返回整数类别,无论哪个类别的和(ItemAmount)最高。例如,如果我有: 目标1: 项目金额=50.00 ItemCategory=1 目标2: 项目金额=

我拥有的是一个LineItem对象和一个名为LineItems的集合,其中包含LineItem对象。我的LineItem对象有一个名为ItemDate(日期时间数据类型)的属性,另一个名为ItemAmount(十进制数据类型)的属性和另一个名为ItemCategory(整数数据类型)的属性

我要做的是在我的集合对象中编写一个函数,该函数将返回整数类别,无论哪个类别的和(ItemAmount)最高。例如,如果我有:

目标1: 项目金额=50.00

ItemCategory=1

目标2: 项目金额=25

ItemCategory=1

目标3: 项目金额=535.00

ItemCategory=2

在本例中,函数应该返回2,因为ItemCategory 2的ItemAmount(535)比ItemCategory 1的ItemAmount(50+25=75)大

这我知道怎么做。但更难的是,我需要它能够随着时间的推移做到这一点,这意味着,如果一个数量很大,比如535,但其他一些对象的数量较小,但距离更近的日期更多,那么它需要在技术上比其他数量“更大”。这几乎就像数量也需要考虑频率一样$10每天发生的金额需要“大于”每年发生一次的500美元,即使500美元每天大于10美元。这几乎就像我需要通过一年的放大镜查看一个月的数据

我希望这个问题有意义

试试这个:

class ListItem
{
    internal DateTime When;
    internal decimal Amount;
    internal int Category;
}

class ListItems
{
    internal List<ListItem> _items = new List<ListItem>();
    internal int GetCategory(DateTime from, DateTime to)
    {
        Dictionary<int, decimal> totals = _items
            .Where(y => y.When >= from && y.When < to)
            .GroupBy(x => x.Category)
            .ToDictionary(
                category => category.Key,
                category => category.Sum(item => item.Amount)
            );
        return totals.Keys
            .Where(category => totals[category] == totals.Values.Max())
            .First();
    }
}
类列表项
{
内部日期时间;
内部小数金额;
内部int类;
}
类列表项
{
内部列表_items=新列表();
内部int GetCategory(日期时间从,日期时间到)
{
字典总计=\u项
.Where(y=>y.When>=from&&y.Whenx.Category)
.ToDictionary(
category=>category.Key,
类别=>category.Sum(项目=>item.Amount)
);
返回总数。键
.Where(category=>totals[category]==totals.Values.Max())
.First();
}
}

Linq有点多,但如果我理解正确,我认为它会起作用。

听起来你可能需要一个旅行窗口总和:选择一个时间段(比如30天),并跟踪该窗口内的项目总数

如果您只需要一个实例(例如,现在结束30天),那么您所需要做的就是在窗口中汇总这些项目。但是,如果您想绘制一个图表,对项目进行排序并执行连续累加是最有效的;添加进入窗口的项目,然后减去离开窗口的项目

要实现一个移动窗口,可以在一个排序列表中使用两个迭代器(以下是伪代码,而不是C#):


根据自上次以来的时间跨度为数量分配权重?您的描述缺乏足够的细节来创建算法。也许你需要简单地用现在和它发生的日期之间的日期差的函数(线性,平方,…)除以这个数量,这样临近的事件就更有价值了?你关心的是年龄还是频率?如果是频率,持续多长时间?你怎么知道这500美元是一次性的还是仅仅是一系列500美元付款中的第一笔?好吧,也许这会有帮助。我正在做的是创建一个.NET程序来管理我的财务。每当我买东西的时候,我都希望能够根据花费最多的类别对收藏进行排序。食物是我每天买的东西,因此我的程序应该正常跟踪它。不过偶尔,我可能会买一些出乎意料的东西。例如,如果我需要为我的打印机购买墨水,那么我真的不需要跟踪它,因为我的钱在购买墨水时没有被“烧掉”。这是一件“一次性”的事情。即使我的交易额可能是100美元,它也不应该每天跟踪这件事。我想我只关心跟踪每周实际发生次数超过几次的事情。
// initialize
acc= 0.0
for(startP= SortedItems.begin; !startP.last; startP.next) {
  if(startP.item.time > graphstart - timewindow) { break }
}
for(endP= startP; !endP.last; endP.next) {
  acc += endP.item.value
  if(endP.item.time > graphstart) { break }
}

// main loop
for(; !endP.last; endP.next) { // advance time window to next item
  endItem= endP.item
  endTime= endItem.time
  for(; !startP.last; startP.next) { // subtract items leaving time window
    startItem= startP.item
    startTime= startItem.time
    if(startTime > endTime - timewindow) { break }
    acc -= startItem.value
    output(startTime + timewindow, acc)  // register graph values coming down
  }
  acc += endItem.value
  output(endTime, acc)  // register graph value going up
}