我有一个具有属性时间和计数的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;
}
答案 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
对象中,但这似乎有点不必要。
显而易见,您可以扩展此方法以维护每日统计数据等。
两个警告:
周很棘手;有些年份有53周,有些有52周。因此,weeklyStats[52]
可能有效,也可能无效。如果我们到了第52周,我选择在第0周时就选择清除它。
weeklyStats[lastItemWeek]
给出的元素不是最终值。