2014-01-16 30 views
0

我有一個具有屬性時間和數量的Stat對象。我有一個(按時間排序)每小時進入的這些對象的列表。我想要集羣顯示。 有沒有一種很好的方式來在目標c中按時間聚類數據?或比以下天真的算法更好的算法?將日期按小時,天,周,月,年進行聚類數據目標c

這是每週做一個例子。其他類似,但您更改日期組件。

-(void) makeWeeklyData{ 

    Stat *prev = self.hourlyData[0]; 
    NSInteger sum = 0; 
    NSMutableArray *weeklyData = [NSMutableArray array]; 
    for (CSInstallStat *data in self.hourlyData) { 
     NSDateComponents *itemComps = [[NSCalendar currentCalendar] components:kCFCalendarUnitWeekOfYear | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:data.time]; 
     [itemComps setCalendar:[NSCalendar currentCalendar]]; 

     NSDateComponents *currComps = [[NSCalendar currentCalendar] components:kCFCalendarUnitWeekOfYear | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:prev.time]; 
     [currComps setCalendar:[NSCalendar currentCalendar]]; 

     if ([itemComps weekOfYear] == [currComps weekOfYear] && [itemComps month] == [currComps month] && [itemComps year] == [currComps year]) {//Same Week 
      sum += data.count; 
     } else if([itemComps weekOfYear] >= [currComps weekOfYear] && [itemComps month] == [currComps month] && [itemComps year] == [currComps year]) { //Next Week 

      Stat *stat = [[CSInstallStat alloc] init]; 
      stat.time = [currComps date]; 
      stat.count = sum; 
      stat.timeAccuracy = ENUMWeekly; 
      [weeklyData addObject:stat]; 
      sum = 0; 
      sum += data.count; 
      prev = data; 
     } else { 
      prev = data; 
     } 

    } 
    self.weeklyData = weeklyData; 


} 
+0

我的[MBCalendarKit](http://github.com/mosheberman/MBCalendarKit)庫包含NSCalendar和NSDate上的一些可能有用的類別。 – Moshe

回答

0

如果我正在實施這種制度,我會傾向於維護統計的對象進來,所以,讓我們說我們有「每週數據」數組,並讓我們說清酒我們想要保持52周的價值。在你的類中,聲明成員變量:

NSCalendar *gregorianCalendar; 
unsigned lastItemWeek; 
struct weekinfo { 
    unsigned frequency; 
    unsigned month; 
    int year; 
} weeklyStats[53]; 

當一個新的價值在於,你只是做

- (id)init 
{ 
    if ((self = [super init])) { 
    ... 
    /* Must fix the calendar we're using, or at least understand the one we're 
     using. Using [NSCalendar currentCalendar] is potentially risky as we 
     don't necessarily know what that is. */ 
    gregorianCalendar = [[NSCalendar alloc] 
         initWithCalendarIdentifier:NSGregorianCalendar]; 
    ... 
    } 
} 

- (void)gotNewItemWithDate:(NSDate *)date 
{ 
    NSDateComponents *itemComps = [gregorianCalendar 
           components:(NSWeekOfYearCalendarUnit 
              | NSCalendarUnitMonth | NSCalendarUnitYear) 
           fromDate:date]; 
    unsigned week = [itemComps week] - 1; // This runs from 0 to 52 inclusive 
    unsigned month = [itemComps month]; 
    int year = [itemComps year]; 

    if (week == lastItemWeek) 
    ++weeklyStats[week].frequency; 
    else { 
    // Some years don't have week 53 (which we store in weeklyStats[52]) 
    if (week == 0 && lastItemWeek == 51) 
     weeklyStats[52] = (struct weekinfo){ 0, 0, 0 }; 

    weeklyStats[week] = (struct weekinfo){ 1, month, year }; 
    } 
    lastItemWeek = week; 
} 

你可以存儲在Stat對象,而不是如果你真的想要,但似乎有點不必要。

同樣顯而易見的是,您可以擴展這種方法來維護日常統計數據等。

兩個警告:

  1. 周是棘手;有些年份有53周,有些有52年。因此,weeklyStats[52]可能有效或不可能有效。如果我們在第52周的最後一週,我選擇在此清除它。

  2. weeklyStats[lastItemWeek]給出的元素不是最終值。

+0

你很難在幾周內編碼年份 - 這對一些日曆系統來說會打破。 – Moshe

+0

@Moshe是的。這就是爲什麼代碼對日曆進行硬編碼的原因,這就是爲什麼在上面的代碼中有關於它的一個重要的評論。當然,如果OP期望使用用戶的本地化日曆而不是公曆(可疑的IMO),這當然只是一個問題。 – alastair

+0

你會很驚訝這種事情。蘋果鼓勵本地化。 – Moshe

相關問題