2012-09-13 68 views
2

我正在開發一個應用程序,該應用程序計算在指定時間段(期限)內產品中獲取的共享。隨着時間的推移,時間變化時的數據聚合

計算完成後,我有必要根據預定義的審閱期將數據彙總到組中(例如,如果獲得產品100%所有權所需的時間爲25年,並且審閱期限值爲5年,我會爲協議設定5組數據彙總)。

我進行聚合,如圖通過我的計算結果集循環:

if (Year% ReviewPeriod == 0) 
      { 
       // Perform Aggregations 
      } 

這在大多數情況下的罰款。 但是,我確實有很多情況,產品在期限結束前達到100%的所有權。

我需要做的是彙總基於ReviewPeriod變量執行的計算,但如果計算中的最終數值不等於審閱期,則根據項目數合計項目剩餘。

例如,給定一個22年的期限,數據將根據審查期間變量進行彙總,但是如果有餘數,則餘數應根據餘數的值進行彙總。

成功範例

年0 - 5 = 5聚合

年6 - 10 = 5分的聚合

年11 - 15 = 5分的聚合

年16 - 20 = 5層的聚合

21 - 22 = 2聚合

任何人都可以用我所描述的邏輯聚合數據來幫助我。

回答

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(); 
      } 
     } 
    } 
} 
+0

我相信這正是作者currenlty **有** .. – quetzalcoatl

+0

我不這麼認爲。他似乎在執行聚合_inside if statement_,而我建議他只在_中開始一個新的聚合,但是在循環體中執行它。通過這種方式,剩餘的年份將被正確添加到最後的聚合中。 –

+0

啊,好吧,對不起,你的意思是「開始」。我誤解了你的評論。你是對的 - 如果他漸進地做,那麼他可能忘了重置計數器。 – quetzalcoatl

1

我想,我的建議是不值得300rep賞金,而任我誤解你的問題,或者您已經衝出賞金..

您計算最終聚合的現有代碼是否正常工作?如果是這樣,則確定喲umay只需使用模(%)的範圍和簡單的數學:

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%所有權的多種情況。「 - 這意味着你在計算中有一個錯誤,而不是在循環中,如果錯誤出現在循環或年邊界檢測中,那麼幾乎所有的錯誤都會關閉,很難說沒有更多的計算代碼

1

你真的沒有給你足夠的代碼繼續下去希望你應該可以使用這個,但是你的循環目前已經設置好了,它會將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. 
} 
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); 
      } 
     } 
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) 
{ 
    //... 
} 
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 
相關問題