我有一个NSDate对象的排序数组。我想要做的是创建一个方法,该方法接受日期并返回YES或NO,具体取决于是否可以在日期数组中找到该日期。
NSArray *dateArray;
-(BOOL)arrayContainsDate(NSDate *)d {
// return YES if d is found in dateArray
}
我知道如何逐个浏览数组的每个元素,但我需要更快的方法。
答案 0 :(得分:4)
在确定一组对象中是否存在对象时,如果您正在为Mac OS开发,请考虑使用NSSet
/ NSMutableSet
对象(或NSOrderedSet
/ NSMutableOrderedSet
X 10.7或iOS 5.0并希望保留集合中元素的顺序)。 NSSet
容器旨在实现高效查找。当一个对象具有合适的hash
(大多数Foundation对象都这样做)时,查找实际上是O(1),这比二进制搜索更快。
NSSet *dateSet = [NSSet setWithArray:dateArray];
if ([dateSet containsObject:date1])
{
// do something
}
请注意,每次构建集合而不是从数组中转换它是很重要的,否则您将失去任何性能优势。
有关详细信息,请参阅here。
由于您想要检查指定日期而不考虑时间,因此您需要在将添加到集合之前截断日期值。例如(选择更好的名称,这只是一个例子):
// potentially add as a category method to NSDate
- (NSDate *) dateByTruncatingTime
{
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:aDate];
return [[NSCalendar currentCalendar] dateFromComponents:components];
}
// ------------- somewhere else -------------
- (void) actionHappened
{
[myMutableSet addObject:[[NSDate date] dateByTruncatingTime]];
}
- (BOOL) didActionHappenOnDate:(NSDate *) aDate
{
return [myMutableSet containsObject:[aDate dateByTruncatingTime]];
}
答案 1 :(得分:1)
在对数组进行排序时,请使用binary search。首先将您的日期与数组的中间元素进行比较(使用compare:
) - 如果相等,则找到它。如果它小于或大于那么重复考虑阵列的前半部分或后半部分。等
您可以使用两个索引来执行此操作 - 您正在考虑的范围的最小值和最大值。计算中间指数,进行比较,然后考虑的新范围是min,middle-1或middle + 1,max。
这个算法是O(log2 N) - 你不会做得更好。
代码留作练习!
HTH
答案 2 :(得分:1)
你可以使用哈希。
NSDictionary *dict = {[NSString stringWithFormat:@"%@",date1]:@"",[NSString stringWithFormat:@"%@",date2]:@""}
- (BOOL) containsDate:(NSDate*)_d
{
return [dict valueForKey:[NSString stringWithFormat:@"%@",_d]] != nil;
}