按日期,日,周,月,年目标c对日期进行聚类

时间:2014-01-16 04:40:00

标签: objective-c nsdate nsdatecomponents

我有一个具有属性时间和计数的Stat对象。我有一个(按时间排序)这些对象的列表,每小时进入一次。我想集群展示。 有没有一种很好的方法可以在目标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;


}

1 个答案:

答案 0 :(得分: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周,我选择在第0周时就选择清除它。

  2. weeklyStats[lastItemWeek]给出的元素不是最终值。