我正在开发一个应用程序,用于计算在指定时间段(期限)内在产品中获得的共享。
在执行计算后,我有必要根据预定义的审核期将数据汇总到组中(例如,如果获得100%产品所有权所需的时间是25年,那么审核期间价值是5年,我将有5套协议的数据汇总。
我通过循环计算结果集来执行聚合:
if (Year% ReviewPeriod == 0)
{
// Perform Aggregations
}
这在大多数情况下都能正常工作。 但是我确实有很多场景,产品在学期结束前达到100%的所有权。
我需要做的是汇总基于ReviewPeriod变量执行的计算,但如果计算中的最终值不等于审核周期,则根据剩余的项目数汇总项目
例如,给定22年的期限,数据将根据Review Period变量进行汇总,但如果有余数,则应根据余数的值汇总余数。
工作示例
0 - 5年级= 5次聚合
第6 - 10年= 5次聚合
11 - 15年级= 5次聚合
16 - 20年= 5次聚合
21 - 22年= 2次聚合
如我所述,任何人都可以帮助我使用逻辑来聚合数据。
答案 0 :(得分:1)
可能最简单的方法是:
for ( int year = 0; year <= max_year; year++ ) {
if ( year % reviewPeriod == 0 ) {
// start a new aggregation
}
// add year to current aggregation
}
您可以保留一个聚合列表,并在每个时段的开头添加一个新聚合。
这是一个工作示例,它只列出了列表中的年份:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Aggregations
{
class Program
{
static void Main(string[] args)
{
int maxYear = 22;
int period = 5;
int year = 1985;
List<List<int>> aggregations = new List<List<int>>();
int i = -1;
for (int y = 0; y <= maxYear; y++)
{
if (y % period == 0)
{
aggregations.Add(new List<int>());
i++;
}
aggregations.ElementAt(i).Add(year);
year++;
}
foreach ( List<int> l in aggregations )
{
foreach (int yy in l)
{
Console.Write(yy + " ");
}
Console.WriteLine();
}
}
}
}
答案 1 :(得分:1)
我认为我的建议不值得300rep赏金,要么我误解了你的问题,要么你已经超过了赏金..
计算最终聚合的现有代码是否运行良好?如果是这样,那么确定范围你可以使用modulo(%)和简单的数学:
int minYear = ...the first year // inclusive, i.e. 1970
int maxYear = ...the last year // inclusive, i.e. 2012
int span = maxYear - minYear + 1; // 1970..2012->43, 2001..2006->6
int fullFives = span / 5; // 1970..2012->8, 2001..2006->1
int remainder = span % 5; // 2001..2006->3, 2001..2006->1
for(int i=0; i<fullFives; ++i)
{
int yearFrom = minYear + 5*i
int yearTo = minYear + 5*(i+1) - 1
// 1970..2012 -> 1970-1974, 1975-1979,1980-1984,1985-1989,1990-1994,1995-1999,2000-2004,2005-2009
// 2001..2006 -> 2001-2005
aggregate(yearFrom, yearTo);
}
if(remainder > 0)
{
int yearFrom = minYear + 5*fullFives
int yearTo = minYear + maxYear
// 1970..2012 -> 2010-2012
// 2001..2006 -> 2006-2006
aggregate(yearFrom, yearTo);
}
这是“凭空”写的,我没有检查/编辑它 - 只是为了勾画这个想法。
注意:您已经说过一切正常但有时候“产品在学期结束前达到100%所有权的情况”。 - 这表明你宁愿在计算中出错,而不是在循环中出错。如果错误在循环或年边界检测中,则可能几乎所有都将关闭。如果没有更多的计算代码被揭示,很难说。
答案 2 :(得分:1)
你还没有给出足够的代码来继续。希望你能够使用它,但是你的循环当前已经设置好了。它将mod值“泄漏”到循环外部;循环结束后,您可以检查最终的mod值以查看剩余的聚合数。
int modValue = 0;
for //foreach/while/... - your loop here
{
...
modValue = Year % ReviewPeriod;
if (modValue == 0)
{
// Perform Aggregations
}
...
} // end of your loop
if (modValue != 0)
{
// Perform final aggregation. There are modValue items to aggregate.
}
答案 3 :(得分:1)
代码示例将在0年,5年级,10年级等时启动,而不是每年启动。
如果您只需要在该代码触发时聚合的年数,并且当产品提前达到100%所有权时可以提前设置该期限,我认为这样可行:
int term = 22;
int reviewperiod = 5;
for (int year = 0; year < term; year++)
{
if (year % reviewperiod == 0)
{
var endyear = Math.Min(year + reviewperiod, term);
Console.WriteLine("Aggregate years {0} to {1}, {2} Aggregations ", year, endyear, endyear - year);
}
}
答案 4 :(得分:1)
你认为像
这样的东西private int reviewPeriod = 5;
public void Aggregate(int term)
{
Enumerable.Range(0, term)
.ToList()
.Foreach(this.AggregateYear);
}
this.AggregateYear
定义如下
public void AggregateYear(int year)
{
var currentRemainder = year % this.reviewPeriod;
var aggregatePeriod = (currentRemainder == 0)
? this.reviewPeriod
: currentRemainder;
this.PerformAggregation(aggregatePeriod);
}
和this.PerformAggregation
定义如下
private void PerformAggregation(int aggregatePeriod)
{
//...
}
答案 5 :(得分:1)
假设这些数据在内存中(因为你没有另外指定),那么你可以使用Linq的GroupBy函数:
struct YearValue
{
public int Year, Value;
}
static void Main()
{
// Create some data, hopefully representative of what you are dealing with...
Random r = new Random();
YearValue[] dataValues = new YearValue[22];
for (int i = 0; i < dataValues.Length; i++)
dataValues[i] = new YearValue {Year = i, Value = r.Next(200)};
// Average of values across 'ReviewPeriod' of five:
foreach (var item in dataValues.AsEnumerable().GroupBy(i => i.Year / 5))
{
YearValue[] items = item.ToArray();
Console.WriteLine("Group {0} had {1} item(s) averaging {2}",
item.Key,
items.Length,
items.Average(i => i.Value)
);
}
}
然后该程序输出以下文字:
Group 0 had 5 item(s) averaging 143.6
Group 1 had 5 item(s) averaging 120.4
Group 2 had 5 item(s) averaging 83
Group 3 had 5 item(s) averaging 145.2
Group 4 had 2 item(s) averaging 98.5