2014-01-16 4 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] может быть или не быть действительным. Я выбрал здесь, чтобы очистить его, когда мы доберемся до недели 0, если последний раз на неделе 52.

  2. Элемент, заданный weeklyStats[lastItemWeek], не является окончательным значением.

+0

Вы несете длинную длину в кодировании в течение нескольких недель - это сломается для некоторых календарных систем. – Moshe

+0

@Moshe Да. Вот почему код также жестко кодирует календарь, и именно поэтому в коде выше есть большой комментарий. Это, конечно, только проблема, если ОП ожидал использовать локализованный календарь пользователя, а не григорианский календарь (сомнительная ИМО). – alastair

+0

Вы бы очень удивились этому. Apple поощряет локализацию. – Moshe

Смежные вопросы